2015-05-06 44 views
3
#include <utility> 

struct A { 
    constexpr auto one(int a) { 
     return std::integral_constant<int, _data[a]>{}; 
    } 
    constexpr int two(int a) const { 
     return _data[a]; 
    } 

    int _data[10]; 
}; 

int main() { 
    constexpr auto ex = A{{1,2,3,4,5,6,7,8,9,10}}; 

    std::integral_constant<int, ex.two(3)> b{}; 
} 

上面的代码不会在主干铛中编译。该错误是在one()成员函数,并说:C++ constexpr自动成员函数。铿锵的问题?

cc.cpp:57:44: note: implicit use of 'this' pointer is only allowed 
    within the evaluation of a call to a 'constexpr' member function. 

显然,函数标记为constexpr,如果你注释掉one()成员,一切编译罚款,所以我们显然能够从创建integral_constantex,但不是直接从struct?这似乎是,当我需要auto返回类型扣除,它失败并声称该功能不是constexpr

这是预期吗?我觉得这不应该是一个问题,如果这是预期的行为,我会感到惊讶。

+2

'_data [a]'不是'A :: one'内的常量表达式。请注意,'constexpr'函数仍然可以在运行时调用,例如如果您提供仅在运行时已知的参数。 – dyp

+0

这是'two'中的一个constexpr,通过使用它的返回值作为模板参数来证明它? – pat

+2

据我所知,'_data [a]'在两个成员函数中都不是一个常量表达式。但是constexpr函数可以由非常量表达式组成。规则是:在需要一个常量表达式的上下文中,不可以评估非常量的东西(包括一个constexpr函数的一部分)。另外,在需要常量表达式的上下文中,必须有一种方法可以合法调用'constexpr'函数。 – dyp

回答

6

如果考虑[dcl.constexpr]/7这样的说法:

constexpr函数调用产生相同的结果作为呼叫为等效的非constexpr功能在各方面除了可以在常量表达式中出现对constexpr函数的调用。

考虑非等效函数A::one()_data[a]不能在常量表达式中使用(作为非类型模板参数),因为它会涉及的this评价中,从[expr.const]:

甲条件表达式e是一个核心常量表达式除非按照 抽象机(1.9)的规则对e的评估将评估以下表达式之一:
(2.1) - this(5.1。1),除了constexpr函数或constexpr构造函数被评估为 的一部分;

由于非constexpr相当于不合格,所以constexpr函数给出相同的结果是合理的。

安大略省另一方面,two()是一个结构良好的成员函数,无论constexpr和你的ex.two(3)用途是作为一个常量表达式有效 - 这就是为什么它编译。

+0

宏伟的答案。你能引用一段标准,告诉为什么'two'在常量表达式中工作吗?在'constexpr'对象上调用方法时''this'获得'constexpr'限定的部分是由我以实验方式确定的。 –

+0

@ polkovnikov.ph该标准提供了一些可以防止表达式成为常量表达式的内容列表 - 只是它们都不适用。除了'constexpr',[]调用函数,而不是'constexpr'函数,[]调用未定义的函数,[] UB,[] lambda,[x]左值到右值的转换但[x] **除非**指的是用'constexpr'定义的对象的不可变子对象,... – Barry

1
  1. constexpr功能是为了使它们可以在编译时和运行时被调用。
  2. 如果您可以省略constexpr并获得正确的普通函数,则具有constexpr函数的代码格式良好。换句话说,它必须编译为运行时功能
  3. 如果constexpr函数的主体不能在编译时计算,它仍然被编译,但不能在编译时上下文中使用它,例如模板参数。
  4. 如果constexpr方法在constexpr对象上调用,this被视为constexpr。

one情况下,它是形成不良的,因为当它编译成在运行时运行,_data[a]被认为是一个运行时的表现,因为a不是一个常量表达式,即使thisthis->_data是。

two情况下,它编译罚款,因为它工作正常运行时,在编译时thisconstexpr尽可能a,使this->_data[a]constexpr,一切工作正常。

+0

删除'one'函数编译好,编译时环境中使用'two'? – pat

+0

从字面上看,在这个例子中,我使用两个作为模板参数的调用。 – pat