如果没有指定第一个模板参数,可以将函数模板的第一个模板参数默认为第二个吗?
这是一个小例子:
#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);
}
这有效,但我想要的是,KeepNegatives
(即ContainerOut
)的返回值类型与输入值的类型相同(即ContainerIn
)如果未指定ContainerOut
。以便编译以下代码行(现在为does not)并返回IntVector
。
auto intVec4 = KeepNegatives(intVector);
答案 0 :(得分:4)
你可以简单地为这种特殊情况添加一个重载:
template <typename ContainerIn>
ContainerIn KeepNegatives(const ContainerIn& xs)
{
return KeepNegatives<ContainerIn, ContainerIn>(xs);
}
然而,这可能会导致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);
}
答案 1 :(得分:3)
更好的方法,例如std::experimental::make_array
,是不直接使用ContainerOut
作为返回类型;这允许您指定标记类型作为默认值(void
是一个简单的选择),然后计算返回类型。
template <typename ContainerOut = void, typename ContainerIn,
typename ret_t = std::conditional_t<std::is_void<ContainerOut>{},
ContainerIn, ContainerOut>>
ret_t KeepNegatives(const ContainerIn& xs){
// ...
}
答案 2 :(得分:1)
您可以将SFINAE与过载相结合,如下所示:
template <typename ContainerOut, typename ContainerIn>
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) {
ContainerIn 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;
}
和main
:
auto intVec2 = KeepNegatives<IntVector>(intList);
auto intList2 = KeepNegatives<IntList>(intVector);
auto intVec3 = KeepNegatives(intVector);
提供一个简单的重载:
template <typename ContainerIn>
ContainerIn KeepNegatives(const ContainerIn& xs) {...}
如果用户明确提供相同的模板参数,则会对重载函数进行模糊调用:
auto intVec3 = KeepNegatives<IntVector>(intVector);