问题是mpl::c_str 的value 成员没有标记为constexpr。在库作者决定包含对constexpr 的支持之前,除非您愿意修改您的Boost 代码(或创建您自己的c_str 版本),否则您几乎完蛋了。如果你决定这样做,修改很简单:你只需要找到BOOST_ROOT/boost/mpl/string.hpp并替换它
template<typename Sequence>
struct c_str
{
...
static typename Sequence::value_type const value[BOOST_MPL_LIMIT_STRING_SIZE+1]
};
template<typename Sequence>
typename Sequence::value_type const c_str<Sequence>::value[BOOST_MPL_LIMIT_STRING_SIZE+1] =
{
#define M0(z, n, data) \
mpl::aux_::deref_unless<BOOST_PP_CAT(i, n), iend>::type::value,
BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
#undef M0
'\0'
};
通过这个
template<typename Sequence>
struct c_str
{
...
static constexpr typename Sequence::value_type value[BOOST_MPL_LIMIT_STRING_SIZE+1] =
{
#define M0(z, n, data) \
mpl::aux_::deref_unless<BOOST_PP_CAT(i, n), iend>::type::value,
BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~)
#undef M0
'\0'
};
};
// definition still needed
template<typename Sequence>
constexpr typename Sequence::value_type c_str<Sequence>::value[BOOST_MPL_LIMIT_STRING_SIZE+1];
嗯,再挖掘一下,发现问题比我想象的要复杂。其实constexpr中可以使用静态常量;真正的问题是c_str<T>::value 是一个数组,而您的函数将指针作为参数。因此,编译器需要衰减数组,这归结为获取其第一个元素的地址。由于地址是一个运行时概念,因此不可能在 constexpr 中获取对象的地址。
为了解决这个问题,我尝试编写isequal 的第二个版本,它对数组而不是指针进行操作:
template <int N, int M>
constexpr bool isequal(char const (&one)[N], char const (&two)[M], int index)
{
return (one[index] && two[index]) ?
(one[index] == two[index] && isequal(one, two, index + 1)) :
(!one[index] && !two[index]);
}
template <int N, int M>
constexpr bool isequal(char const (&one)[N], char const (&two)[M])
{
// note: we can't check whether N == M since the size of the array
// can be greater than the actual size of the null-terminated string
return isequal(one, two, 0);
}
constexpr char hello[] = "hello";
static_assert(isequal(hello, hello), "hello == hello");
constexpr char zello[] = "zello";
static_assert(!isequal(hello, zello), "hello != zello");
constexpr char hel[] = "hel";
static_assert(!isequal(hello, hel), "hello != hel");
很遗憾,此代码不适用于mpl::c_str;实际上,问题在于静态 const 数组不是编译时值,这与整数常量不同。所以我们又回到了起点:除非value 被标记为constexpr,否则无法在常量表达式中使用它。
至于我最初给出的代码为什么失败,我现在无法回答我的 gcc (4.6) 版本fails to compile it altogether...
更新 gcc 后,发现 value 需要在类外部定义,即使它是在类中声明和初始化的(参见 this question)。我用更正编辑了上面的代码。