引用初始化和常量表达式

时间:2017-12-20 17:00:06

标签: c++ language-lawyer c++17

作为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();

2 个答案:

答案 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不适合类类型的对象,指针类型或类/数组类型,因此它不符合条件。