函数模板:默认第一个模板参数为第二个

Tob*_*ann 4 c++ templates types c++11 c++14

如果未指定第一个参数,是否可以将函数模板的第一个模板参数默认为第二个?

这是一个小例子:

#include <algorithm>
#include <list>
#include <vector>

template <typename ContainerOut, typename ContainerIn>
ContainerOut KeepNegatives(const ContainerIn& xs)
{
    ContainerOut result;
    auto itOut = std::inserter(result, std::end(result));
    auto isNegative = [](auto x){ return x < 0; };
    std::copy_if(std::begin(xs), std::end(xs), itOut, isNegative);
    return result;
}

int main()
{
    typedef std::vector<int> IntVector;
    typedef std::list<int> IntList;

    IntVector intVector = { 1, -2, -3, 4 };
    IntList intList = { 1, -2, -3, 4 };

    auto intVec2 = KeepNegatives<IntVector>(intList);
    auto intList2 = KeepNegatives<IntList>(intVector);
    auto intVec3 = KeepNegatives<IntVector>(intVector);
}
Run Code Online (Sandbox Code Playgroud)

这有效,但我想要的是,KeepNegatives(ie ContainerOut)的返回值的类型与输入值的类型 (ie ContainerIn)的类型相同,以防ContainerOut未指定。这样下面的代码行就会编译(现在还没有)并返回一个IntVector.

    auto intVec4 = KeepNegatives(intVector);
Run Code Online (Sandbox Code Playgroud)

Ros*_*lav 5

您可以简单地为这种特殊情况添加一个重载:

template <typename ContainerIn>
ContainerIn KeepNegatives(const ContainerIn& xs)
{
    return KeepNegatives<ContainerIn, ContainerIn>(xs);
}
Run Code Online (Sandbox Code Playgroud)

但是,这可能会导致您的intVec3情况模棱两可。这是解决它的一种方法:

#include <algorithm>
#include <list>
#include <vector>

template <typename ContainerOut, typename ContainerIn, 
          typename = std::enable_if_t<!std::is_same<ContainerOut, ContainerIn>::value>>
ContainerOut KeepNegatives(const ContainerIn& xs)
{
    ContainerOut result;
    auto itOut = std::inserter(result, std::end(result));
    auto isNegative = [](auto x){ return x < 0; };
    std::copy_if(std::begin(xs), std::end(xs), itOut, isNegative);
    return result;
}

template <typename ContainerIn>
ContainerIn KeepNegatives(const ContainerIn& xs)
{
    return KeepNegatives<ContainerIn, ContainerIn, void>(xs);
}


int main()
{
    typedef std::vector<int> IntVector;
    typedef std::list<int> IntList;

    IntVector intVector = { 1, -2, -3, 4 };
    IntList intList = { 1, -2, -3, 4 };

    auto intVec2 = KeepNegatives<IntVector>(intList);
    auto intList2 = KeepNegatives<IntList>(intVector);
    auto intVec3 = KeepNegatives<IntVector>(intVector);
    auto intVec4 = KeepNegatives(intVector);
}
Run Code Online (Sandbox Code Playgroud)

居住