首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >lvalue到rvalue转换是否应用于非类型lvalue模板参数?

lvalue到rvalue转换是否应用于非类型lvalue模板参数?
EN

Stack Overflow用户
提问于 2022-09-24 12:42:30
回答 1查看 118关注 0票数 3
代码语言:javascript
复制
struct S{
   constexpr S() {};
};
template <auto x> void f();

int main() {

    S s{};
    f<s>();
}

首先,每个[temp.arg.nontype]/1

如果模板参数(13.2)的类型T包含占位符类型(9.2.9.6)或包含推导类类型的占位符(9.2.9.7),则该参数的类型是为本发明声明中的变量x推导的类型。 T=模板-参数; 如果模板参数声明(13.2)不允许推导参数类型,则程序格式不正确。

我们的模板参数包含占位符类型auto,因此参数的类型是为本发明的声明auto x = s;中的变量x推导的类型,参数的类型是S,而S是参数声明的允许类型,因为S是一种结构文字类型。

第二,per [temp.arg.nontype]/2

非类型模板参数的模板参数应该是模板参数类型的转换常量表达式(7.7)。

这意味着模板参数s应该是一个转换的常量表达式。每[expr.const]/10

类型T的转换常量表达式是隐式转换为T类型的表达式,其中转换的表达式是常量表达式,隐式转换序列仅包含

  • 。。
  • (10.2) -lvalue-rvalue转换(7.3.2)
  • 。。

在应用任何隐式转换之前,我不确定lvalue s是否被转换为prvalue。注意,C++14中转换的常量表达式的定义相对变化。N4140§5.19 [expr.const]/3: (重点地雷)

T类型的转换常量表达式是一个表达式,隐式转换为T类型的prvalue,其中转换的表达式是核心常量表达式,而隐式转换序列只包含。

因此,按照C++14,在对其应用任何隐式转换之前,都可以保证将转换后的表达式转换为prvalue。

我不太确定从lvalue到rvalue的转换是否应用于模板参数s。换句话说,我不确定lvalue s是否被转换为prvalue。

因此,一般来说,如果我将lvalue作为非类型模板参数的模板参数传递,那么lvalue到rvalue的转换是否应用于该lvalue?

除此之外,是s https://timsong-cpp.github.io/cppwp/n4868/expr.const#2对象

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-25 16:53:19

expr.const/10的含义是,每当一个表达式出现在需要“转换为T类型的常量表达式”的上下文中时,该表达式就被“隐式转换为T类型”,并且应适用expr.const/10中的附加限制。

因此,在应用任何隐式转换之前,s不会“转换为prvalue”。相反,s被隐式转换为S类型,这种隐式转换可能涉及一些标准和/或用户定义的转换,例如从lvalue到rvalue的转换。要知道它是否存在,我们必须查看隐式转换的规则,这些规则都在conv.general中。特别是[conv.general]/6

任何隐式转换的效果与执行相应的声明和初始化,然后使用临时变量作为转换的结果相同。如果T是lvalue引用类型或函数类型的rvalue引用(dcl.ref),则结果是lvalue,如果T是对对象类型的rvalue引用,则为xvalue,否则为prvalue。表达式E被用作glvalue当且仅当初始化时使用它作为glvalue。

我相信这里的措辞是旧标准版本的遗物。应该说(在现代语言中),当T是一种非引用类型时,E到T的隐式转换会产生一个prvalue,该值初始化其结果对象(称为t),就像通过T t = E;进行的那样。

因此,我们考虑S t = s;,这个初始化是做什么的?它调用S的复制构造函数来初始化t[dcl.init.general]/16.6.2.1。在此场景中不存在lvalue到rvalue的转换。(类类型的Lvalue到rvalue转换很少,但在语言中的某些地方确实发生,例如[expr.call]/12[expr.cond]/7。如果在s上执行了lvalue到rvalue的转换,那么它也将调用复制构造函数;[conv.lval]/3.2。但在这种情况下,语言的规则不需要从lvalue到rvalue的转换。)

因此,使用s作为S类型的模板参数的模板参数的结果是生成一个prvalue,它通过调用以s作为参数的复制构造函数来初始化其结果对象。(这个特定的复制构造函数被隐式定义为不执行任何操作,因为没有子对象要复制。)

这回答了您关于是否应用lvalue到rvalue转换的问题。(您可能想知道prvalue实际上发生了什么,复制构造函数是否真的被调用了,但这是我现在不想讨论的另一个主题,因为它会使这个答案太长。)

至于s是否是常量初始化的,是的。它满足(2.1) (因为它有一个初始化程序)和(2.2),因为它的初始化的全部表达式是一个常量表达式(没有什么可以阻止它成为一个常量表达式,因为它除了调用constexpr默认构造函数之外什么也不做,它本身什么也不做)。不过,我不知道这和你的另一个问题有什么关系。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73837306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档