問題は、 のvalue
メンバーがmpl::c_str
としてマークされていないこと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
この問題を解決するために、ポインターではなく配列で動作するの 2 番目のバージョンを作成しようとしました。
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)では完全にコンパイルできないため、今は答えられません...
gcc を更新した後value
、クラスで宣言および初期化されていても、クラスの外部で定義する必要があることがわかりました (この質問を参照してください)。上記のコードを修正して編集しました。