对可以传递给自动模板参数的内容有限制吗?

时间:2018-12-13 12:30:23

标签: c++ templates parameters c++17 auto

中,我们得到了auto template parameters。我试图在此问题中使用一个传递对象:Can I Write Relational Operators in Terms of Arithmetic Operations?但在AndyG's comment的指导下,我发现它没有编译:(

使用模板功能:

template <auto T>
void foo()

我可以作为模板参数传递的内容似乎受到限制。例如,从我的链接问题中可以看出,我似乎无法传递函子:

foo<plus<int>{}>()

是否存在允许和不允许的清单?

2 个答案:

答案 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>实际上也没有定义任何比较运算符-因此您仍然不能将其用作非类型模板参数。