【问题标题】:Are There Restrictions on What can be Passed to auto Template Parameters? [duplicate]可以传递给自动模板参数的内容是否有限制? [复制]
【发布时间】:2018-12-13 12:30:22
【问题描述】:

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

给定模板函数:

template <auto T>
void foo()

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

foo<plus<int>{}>()

是否在某处列出了允许和禁止的内容?

【问题讨论】:

  • 与没有auto 的限制相同:stackoverflow.com/Questions/5687540/… 关于即将到来的 C++20 中的更改,请参阅顶部答案的 cmets。
  • @AndyG 我的意思是如果没有自动完成我一文不值:J

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


【解决方案1】:

我相信这完全由以下标准语句处理:

[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]),没有可变或易失的子对象,并且如果存在默认成员运算符,则将其声明为公共,

(4.2) 一个左值引用类型,

(4.3) 包含占位符类型 ([dcl.spec.auto]) 的类型,或

(4.4) 推导类类型的占位符 ([dcl.type.class.deduct])。

5: [ 注意:其他类型要么在下面明确地被禁止,要么被控制模板参数([temp.arg])形式的规则隐含地禁止。 —— 尾注 ] 在确定其类型时,模板参数上的顶级 cv 限定符将被忽略。

【讨论】:

  • 那么......是否有一个“不允许模板参数声明”的列表?我想这就是我的问题的答案。
【解决方案2】:

在 C++17 中,可以在 [temp.param]/4 中找到限制:

非类型模板参数应具有以下类型之一(可选 cv 限定):

  • 整数或枚举类型,
  • 指向对象的指针或指向函数的指针,
  • 对对象的左值引用或对函数的左值引用,
  • 指向成员的指针,
  • std​::​nullptr_­t,或
  • 包含占位符类型的类型。

[temp.arg.nontype]/2 中的参数有额外限制:

对于引用或指针类型的非类型模板参数,常量表达式的值不应引用(或对于指针类型,不应是地址):

  • 一个子对象,
  • 一个临时对象,
  • 字符串文字,
  • typeid 表达式的结果,或
  • 预定义的_­_­func_­_ 变量。

你出错的地方是std::plus&lt;int&gt; 不是一个有效的非类型模板参数。第一个列表中没有这些东西。


在 C++20 中,可以用作非类型模板参数的类型种类将大大扩展。我们将能够使用类类型作为非类型模板参数,只要这些类类型满足所谓的“强结构相等性”。在当前的草案中,这是根据公共定义的,默认为operator&lt;=&gt;。在 P1185 中,目前正在运行并可能被采用,它会略有变化,以 public 的形式定义,默认为operator==

但即使在 C++20 中,std::plus&lt;int&gt; 实际上也没有定义任何比较运算符 - 因此您仍然无法将其用作非类型模板参数。

【讨论】:

  • 所以只是在这里检查,但operator==不是默认定义的吗?意思是,我认为,在 C++20 之后 plus&lt;int&gt; 被允许,对吧?
  • @JonathanMee 不,不是。
  • 哦,诅咒,是的,这是默认定义的赋值:(
猜你喜欢
  • 2012-01-11
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 2014-07-12
  • 1970-01-01
  • 2017-07-08
  • 2019-01-17
  • 2022-12-03
相关资源
最近更新 更多