在c++17中,我们得到了auto
template parameters。我试图在此问题中使用一个传递对象:Can I Write Relational Operators in Terms of Arithmetic Operations?但在AndyG's comment的指导下,我发现它没有编译:(
使用模板功能:
template <auto T>
void foo()
我可以作为模板参数传递的内容似乎受到限制。例如,从我的链接问题中可以看出,我似乎无法传递函子:
foo<plus<int>{}>()
是否存在允许和不允许的清单?
答案 0 :(得分:3)
我相信这完全由以下标准声明处理:
[temp.arg.nontype]
1: 如果模板参数([temp.param])的类型T包含占位符类型([dcl.spec.auto])或推导类类型的占位符([dcl.type.class.deduct]),则参数的类型是在发明的声明中为变量x推导的类型T x = template-argument ;
如果模板参数声明([temp.param])不允许使用推导的参数类型,则程序格式错误。
允许传递函子类型。不能传递函子实例,就像不能传递struct A {};
实例一样。
关于允许使用哪些非类型模板参数:
4: 非类型模板参数应具有以下(可选的,具有cv限定)类型之一:
(4.1) 类型为文字的,具有强等式结构([class.compare.default]),没有可变的或易失的子对象,并且如果存在默认的成员运算符<=>,则将其声明为public
(4.2) 左值引用类型,
(4.3) 包含占位符类型([dcl.spec.auto])的类型,或
(4.4) 推导的类类型([dcl.type.class.deduct])的占位符。
5: [注意:控制模板参数形式的规则([temp.arg])不允许在下面明确或隐含其他类型。 —注 ] 确定模板参数的类型时,将忽略模板参数上的顶级cv限定词。
答案 1 :(得分:2)
在C ++ 17中,可以在[temp.param]/4中找到该限制:
非类型模板参数应具有以下类型之一(可选的cv限定):
- 整数或枚举类型
- 指向对象的指针或指向函数的指针,
- 对对象的左值引用或对函数的左值引用
- 成员的指针,
std::nullptr_t
或- 包含占位符类型的类型。
对[temp.arg.nontype]/2中的参数有附加限制:
对于引用或指针类型的非类型模板参数,常量表达式的值不得引用(或对于指针类型,不得为其地址):
- 子对象
- 一个临时对象
- 字符串文字,
typeid
表达式的结果,或者- 预定义的
__func__
变量。
您要出错的地方是std::plus<int>
不是有效的非类型模板参数。在那第一个列表中没有这些东西。
在C ++ 20中,可以用作非类型模板参数的类型种类将大大扩展。我们将能够使用类类型作为非类型模板参数,只要这些类类型满足“强结构相等性”的要求。在当前草案中,这是根据公开定义的,默认为operator<=>
。在P1185中,目前正在飞行中并且很可能会被采用,它将稍作更改,以公开定义,默认为operator==
。
但是即使在C ++ 20中,std::plus<int>
实际上也没有定义任何比较运算符-因此您仍然不能将其用作非类型模板参数。