函数模板:将第一个模板参数默认为第二个
function template: default first template argument to second
如果没有指定函数模板的第一个模板参数,是否可以将其默认为第二个?
这里有一个小例子:
#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);
}
这是有效的,但我想要的是,在未指定ContainerOut
的情况下,KeepNegatives
(即ContainerOut
)的返回值的类型与输入值(即ContainerIn
)的类型相同。因此,下面的代码行将进行编译(现在没有)并返回一个IntVector
。
auto intVec4 = KeepNegatives(intVector);
您可以简单地为这种特殊情况添加一个重载:
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);
}
实时
例如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){
// ...
}
您可以将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);
相关文章:
- 使函数参数默认为周围范围
- 如何将值传递给其参数(默认参数)
- 当“std::make_index_sequence”和“std::index_sequence”用于模板参数默认类型时
- C ,构造器中允许的参考参数默认值
- 哪些规则控制参数默认赋值?
- 错误:上一个规范后给出的参数默认参数
- 是否可以设计一个包含模板参数默认值的类
- 构造函数中参数C++默认值
- 如何设置依赖于其他参数的参数默认值
- C++模板参数默认函数实现
- QInput对话框参数默认值
- g++4.8.2上列表方法参数默认初始化时出错
- 在函数定义中指定参数默认值会导致错误 C2143:语法错误:'='之前缺少')'
- 函数模板:将第一个模板参数默认为第二个
- 模板模板参数默认可以引用其他模板类型的参数
- 参数默认为先例参数的值
- 如何修改一个类,使它只有一个成员函数,所有参数默认
- 内置类型的模板参数默认值
- 是否可以使用构造函数或对象作为其他类方法的参数默认值?
- 模板参数默认为更高版本