我读了一点CLang标准库的实现,它让我在const和constexpr上感到困惑。混合使用constexpr和const?
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,它明确指出,常量数据不能保证是一个编译时间常数,请看下面的例子,
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;
然而,读℃后++标准草案N3225,我看到无处明确指出的是,上述实施例应导致错误。特别地,从7.1.5/9,
在 对象声明使用的constexpr指定符为const对象 。这样的对象应该具有文字类型并且应该被初始化。 如果通过构造函数 进行初始化,则构造函数应该是 constexpr构造函数,并且构造函数的每个 参数应为 常量表达式。该呼叫应该是 是一个常数表达式(5.19)。 否则, 出现在其初始化程序中的每个全表达式应为 常量表达式。
因此,如果constexpr int limit = 2 * S :: size;是无效的,那么S :: size不能是一个常量表达式,那么从5.19(常量表达式),在上面的例子中我看不到任何标准的不允许2 * S :: size不是一个常量表达式。
有人可以指出我忽略的任何东西吗?非常感谢你。
嗨,谢谢。我忽略了它。然而,尽管我确实发现很多人在互联网上说过这些,但我仍然没有发现标准提到的地方:赋值运算符期望右边是右值,二元算术运算符期望它们的两个操作数都是右值。 – user534498 2011-02-15 06:01:26