作为this question的后续,gcc和clang都认为这个程序格式不正确:
ri
错误是关于0
在常量表达式中不可用的值。 int
肯定是一个核心常量表达式,并且作为一个prvalue核心常量表达似乎满足these constraints(通常,因为ri
不是类,指针或数组类型) 。所以不应该struct X { };
int main() {
const X& rx = X{};
constexpr X x = rx;
}
满足this criteria吗?
如果我使用类类型的prvalue文字,也是如此:
var products = _context.ProductCategories
.Select(category => new ViewModelProductCategory
{
Id = category.Id,
ParentId = category.ParentId,
Title = category.Title,
SortOrder = category.SortOrder,
NumOfProducts = category.ProductInCategory.Count()
Products = category.ProductInCategory
.Select(pic => new ViewModelProduct
{
Id = pic.Product.Id,
Title = pic.Product.Title,
Price = pic.Product.Price,
Info = pic.Product.Info
}
.ToList();
}).ToList();
答案 0 :(得分:5)
在此声明中:
const int& ri = 0;
0
是prvalue,但ri
未从该prvalue初始化。 prvalue首先经历temporary materialization conversion,并且引用绑定到结果glvalue。由于ri
绑定到这个物化的glvalue,而不是像你(我)怀疑的那样直接绑定到prvalue,相关的限制不是prvalue核心常量表达式限制(0
确实满足)而是 glvalue 核心常量表达式限制 - 实体为permitted result of a constant expression。这种限制,略微提高了清晰度,是:
具有静态存储持续时间的对象是:
- 不是临时对象,或
- 一个临时对象,其值满足上述约束,
或它是一种功能。
我们的glvalue 是一个临时对象,其值满足"上述约束" ("以上"这里指的是prvalue核心常量限制,int
平凡满足),但它不具有静态存储持续时间。
没有静态存储持续时间→实体不是常量表达式的允许结果→glvalue表达式不是常量表达式→ri
未使用常量表达式ri
进行初始化无法在核心常量表达式中使用→i
的声明格式不正确。
同样的论点也适用于适当的类类型。
答案 1 :(得分:1)
正如您所指出的,2.11规定核心常量表达式不得评估为:
一个id-expression,它引用引用类型的变量或数据成员,除非引用具有先前的初始化和 任
- 使用常量表达式
初始化
进一步的expr.const#6:
常量表达式是glvalue核心常量表达式 指的是一个允许的常量结果的实体 表达式(如下定义)或prvalue核心常量表达式 其值满足以下约束条件:
...
如果是实体,则实体是常量表达式的允许结果 具有静态存储持续时间的对象,它不是临时的 object或是一个临时对象,其值满足上述要求 约束,或者它是一种功能。
从我的阅读中,这意味着const X& r =
的RHS(某些类型的替代X)必须是具有静态存储持续时间的对象或一个符合以上标准。由于int
不适合类类型的对象,指针类型或类/数组类型,因此它不符合条件。