混合使用constexpr和const?

use*_*498 8 c++ const clang c++11

我读了一些标准库的CLang实现,它让我对const和constexpr感到困惑.

template<class _Tp, _Tp __v>
struct integral_constant
{
    static constexpr _Tp value = __v;
};

template<class _Tp, _Tp __v>
const _Tp integral_constant<_Tp, __v>::value;
Run Code Online (Sandbox Code Playgroud)

令我困惑的是,它在类定义和const外部使用constexpr.我的问题是,是允许的吗?在什么情况下const和constexpr可以互换使用?当然constexpr函数不能应用于const,所以我说的是const数据和constexpr数据.

我确实在http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf上阅读了一些标准草案和提案 ,但这让我感到更加困惑.所以我还有一些问题,

在N2235中,它明确指出,const数据不能保证是编译时常量,请参见下面的示例,

struct S {
    static const int size;
};
const int limit = 2 * S::size; // dynamic initialization
const int S::size = 256;
Run Code Online (Sandbox Code Playgroud)

和constexpr应该解决这个问题,所以至少在这种情况下,constexpr不允许如下,

struct S {
    static const int size;
};
constexpr int limit = 2 * S::size; // shall be error in my understanding
const int S::size = 256;
Run Code Online (Sandbox Code Playgroud)

但是,在阅读了C++标准草案N3225之后,我看到没有明确说明上面的例子会导致错误.特别是从7.1.5/9开始,

对象声明中使用的constexpr说明符将对象声明为const.这样的对象应具有文字类型并应初始化.如果它是由构造函数调用初始化的,那么构造函数应该是constexpr构造函数,构造函数的每个参数都应该是一个常量表达式.该调用应为常量表达式(5.19).否则,其初始化程序中出现的每个完整表达式都应是一个常量表达式.

因此,如果constexpr int limit = 2*S :: size; 是无效的,那么S :: size不能是一个常量表达式,那么从5.19(常量表达式),我看不到上面例子中的标准不允许2*S :: size不是常量表达式.

任何人都可以指出我忽略的一切吗?非常感谢你.

Fre*_*urk 4

根据 N3225 \xc2\xa75.19p2,S::size 不是常量表达式:

\n\n
\n

条件表达式是常量表达式,除非它涉及以下之一\xe2\x80\xa6

\n\n
    \n
  • 左值到右值的转换 (4.1),除非它应用于\n \n
      \n
    • 整数或枚举类型的泛左值,引用具有前面初始化的非易失性 const 对象,并使用常量表达式进行初始化,或者
    • \n
    • [其他不适用的条件]
    • \n
  • \n
\n
\n\n

请注意我引用的第二个要点如何允许本身使用常量表达式初始化的整数静态数据成员也成为常量表达式,但您的 S::size 未初始化。

\n\n

(旁注:常量表达式是根据条件表达式定义的,因为这就是 C++ 语法的工作原理。)

\n\n

如果您想知道左值到右值的转换是如何发生的,请参阅 \xc2\xa75p9:

\n\n
\n

每当左值表达式作为需要该操作数纯右值的运算符的操作数出现时,左值到右值 (4.1)、数组到指针 (4.2) 或函数到指针 (4.3) 标准转换为用于将表达式转换为纯右值。

\n
\n\n

这可能是一个很好的例子,说明阅读标准并不能成为一个很好的参考,尽管 0x 还没有太多其他可用的内容。

\n