6

文字列の内容に基づいてコード生成を制御できるため、リテラル演算子に渡された文字列を MPL シーケンスに変換できると便利です。以前は、constexpr 関数の引数は関数本体内で定数式と見なされないため、これは不可能であると考えていました。ただし、Clang 3.4.2 および GCC 4.8.2 でコンパイルする次の回避策を思い付きました。

#include <cstdint>
#include <iostream>
#include <typeinfo>

struct string
{
    const uintmax_t m_str[64];
    const size_t m_length;

    template <class... Ts>
    constexpr string(const Ts... ts) :
    m_str{(uintmax_t)ts...}, m_length{sizeof...(Ts)} {}

    constexpr size_t size() const { return m_length; }
    constexpr size_t length() const { return m_length; }
    constexpr uintmax_t operator[](size_t n) const { return m_str[n]; }
};

template <uintmax_t... Ts> struct sequence {};

constexpr auto
operator"" _tag(const char* str, size_t n)
{
    return n == 0 ? string{} :
           n == 1 ? string{str[0]} :
           n == 2 ? string{str[0], str[1]} :
           n == 3 ? string{str[0], str[1], str[2]} :
           n == 4 ? string{str[0], str[1], str[2], str[3]} :
           n == 5 ? string{str[0], str[1], str[2], str[3], str[4]} :
                    string{str[0], str[1], str[2], str[3], str[4], str[5]};
}

int main()
{
    static constexpr auto string = "Hello!"_tag;
    using sequence = sequence<string[0], string[1], string[2], string[3], string[4], string[5]>;
    std::cout << typeid(sequence{}).name() << std::endl;
}

出力:

sequence<72ul, 101ul, 108ul, 108ul, 111ul, 33ul>

質問

このコードは未定義の動作を引き起こしますか、それとも合法ですか?

4

1 に答える 1