2015-09-27 130 views
5

请考虑以下两个C++ 14的方案:constexpr成员函数不使用这个?

计划1:

struct S { constexpr int f() const { return 42; } }; 
S s; 
int main() { constexpr int x = s.f(); return x; } 

方案2:

struct S { constexpr int f() const { return 42; } }; 
int g(S s) { constexpr int x = s.f(); return x; } 
int main() { S s; return g(s); } 

既不是,一个或两个这些程序的不良形成的?

为什么/为什么不呢?

回答

2

这两个程序都格式良好。 C++ 14标准要求是一个常量表达式,因为它被用来初始化一个constexpr变量,事实上它是一个核心常量表达式,因为没有理由不这样做。表达式可能不是核心常量表达式的原因列在5.19 p2节中。尤其是,它声明表达式的评估将不得不做几件事之一,其中没有一件是在你的例子中完成的。

这可能会令人惊讶,因为在某些情况下,将非常量表达式传递给constexpr函数可能会导致结果为非常量表达式,即使未使用该参数也是如此。例如:

constexpr int f(int) { return 42; } 

int main() 
{ 
    int x = 5; 
    constexpr y = f(x); // ill-formed 
} 

然而,这是形成不良的原因是因为左值到右值转换非恒定表达的,这是的事情之一是,表达的评价是不允许的。在调用的情况下不会发生左值到右值的转换。

-3

这听起来像一个测验的问题,而不是由学生提出,但教授的计算器测试公众开放,但让我们来看看......

让我们先从一个定义规则。很明显,两个版本都没有违反这个规定,所以他们都通过了这个部分。

然后,以语法。没有语法错误,如果您不介意语法和语义问题的潜在混合,它们都可以顺利编译。

首先,更简单的语义问题。这不是一个语法问题,但是在两个版本中,f()都是一个结构的成员,并且该函数显然不改变拥有的结构,它返回一个常量。尽管该函数被声明为constexpr,但它并没有声明为const,这意味着如果有理由将其作为运行时函数调用,那么如果尝试在const S上进行尝试,则会产生错误,这会影响两个版本。

现在,可能模糊return g(S());显然,外g是一个函数调用,但因为这将是如果写成return g(S{});随着S可以不那么清楚{}初始化S,也将在未来没有歧义应struct S是用一个运算符()扩展(结构几乎类似于一个仿函数)。被调用的构造函数现在是自动生成的,并且在这个版本中没有operator()为编译器产生混淆,但现代C++ 14应该提供更清晰的选择来避免“最烦人的分析”,其中g(S ())类似。

所以,我不得不说,基于语义规则,他们都失败(虽然并不那么糟糕)。

+0

的成员函数省略常量是无意的,虽然我不知道,如果它会影响示例的不合理性(或其他方面)。以防万一。 –

+0

为了清晰起见,我还将默认构造的S更改为第二个示例中的局部变量。 –

+0

我自己并不是100%,但是它只调用函数显然作为const操作的语义问题,但不是(或不是)声明为const,所以如果S传递为一个const&S或类似的f()被调用。我实际上以为你在这里测试美国;) – JVene

0

我似乎无法在标准中找到一个引人注目的通道或示例,它直接解决了在非constexpr实例上调用constexpr成员函数的问题,但这里有些可能有所帮助(来自草案N4140 ):

[C++14: 7.1.5/5]

对于非模板,非缺省constexpr功能或非模板,非默认的,非继承 constexpr构造中,如果没有参数的值是否存在,使得调用函数或构造函数 可能是一个eval一个核心常量表达式(5.19)的子表达式,该程序是不合格的;没有 需要诊断。

constexpr int f(bool b) 
    { return b ? throw 0 : 0; }  // OK 
constexpr int f() { return f(true); } // ill-formed, no diagnostic required 

从这个我认为这个节目是不是完全形成不良仅仅因为一个constexpr函数有一个可能的非constexpr路径。

[C++14: 5.19]

int x; // not constant 
struct A { 
    constexpr A(bool b) : m(b?42:x) { } 
    int m; 
}; 
constexpr int v = A(true).m; // OK: constructor call initializes 
          // m with the value 42 
constexpr int w = A(false).m; // error: initializer for m is 
           // x, which is non-constant 

这是稍微接近于您的示例程序,这里constexpr构造可以根据参数的值引用非constexpr变量,但没有错误,如果这条道路是没有实际采取。

所以我不认为呈现两个程序应该形成不良的,但我不能提供令人信服地证明:)

相关问题