【发布时间】:2011-02-15 01:57:16
【问题描述】:
我读了一点标准库的 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;
让我感到困惑的是,它在类定义内部使用 constexpr 而在外部使用 const。我的问题是,这是否允许?在什么情况下 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;
而 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;
但是,在阅读了 C++ 标准草案 N3225 之后,我没有看到任何地方明确指出上述示例会导致错误。特别是从 7.1.5/9 开始,
一个 constexpr 说明符用于 对象声明声明对象 作为常量。这样的对象应具有 文字类型并且应该被初始化。 如果由构造函数初始化 调用,构造函数应为 constexpr 构造函数和每个 构造函数的参数应该是 常量表达式。该电话应 是一个常数表达式(5.19)。 否则,每一个完整的表达式 出现在其初始化程序中的应为 常量表达式。
因此,如果 constexpr int limit = 2 * S::size;是无效的,那么 S::size 一定不是常量表达式,那么从 5.19(常量表达式)开始,我看不到标准不允许上例中的 2 * S::size 不是常量表达式。
谁能指出我忽略了什么?非常感谢。
【问题讨论】: