另一个字符串文字,UDL迷宫

Che*_*tor 6 c++ visual-c++ c++17

注意:这是MSVC,C ++ 17问题。

免责声明:我知道已经尝试过了,是的,我正在尝试找到相关的SO答案。

我可以对UDL进行编码,以std::array在编译时将数字文字转换为:

    // std::array{ '1','2','3' }
    constexpr auto a_1 = 123_std_char_array;

    // std::array{ '0','x','1','2' }
    constexpr auto a_2 = 0x12_std_char_array;

    // std::array{ '4'.'2','.','1','3' }
    constexpr auto a_3 = 42.13_std_char_array;
Run Code Online (Sandbox Code Playgroud)

这是我创建的UDL:

    template< char ... Chs >
inline constexpr decltype(auto) operator"" _std_char_array( )
{
    // append '\0'
    return  std::array { Chs..., char(0) } ;
}
Run Code Online (Sandbox Code Playgroud)

令人惊叹,时髦,现代,等等,等等,等等。但是。

问题

我如何编写一个UDL来实现此目的:

    // std::array {'S','t','r','i','n','g'}
    constexpr auto std_char_array_buff_ = 
         "String"_std_char_array ;
Run Code Online (Sandbox Code Playgroud)

请使用MSVC C ++ 17。

告白

我知道要“捕获”字符串文字的UDL必须具有以下占用空间:

  inline auto operator"" _X( const char*, size_t);
Run Code Online (Sandbox Code Playgroud)

我知道在编译时如何将字符串文字转换为std :: array。但是没有UDL。请参阅此处,以获取灵感。

是的,我知道C ++ 20将添加UDL模板,而GCC,clang现在还有其他功能。尽管我看不出有什么帮助。

最后,我知道我可以做到这一点:

     constexpr auto string_view_ = "String"sv ;
Run Code Online (Sandbox Code Playgroud)

L. *_* F. 2

不幸的是,这在 C++17 中似乎不可能。用户定义的字符串文字只能匹配operator""X(str, len)[ lex.ext]/5。那么,len是一个函数参数,函数参数不能转换为模板参数。就像你不能这样做一样:

template <int N>
struct S {};

constexpr auto f(int n)
{
    return S<n>{}; // no, n is not guaranteed to be known at compile time
}
Run Code Online (Sandbox Code Playgroud)

"foo"sv之所以有效,是因为大小不是 的模板参数std::basic_string_view,而是一个“运行时”属性,而它恰好受益于constexpr。你不能这样做,std::array因为大小是 的模板参数std::array

make_array之所以有效,是因为它不是文字运算符,因此它可以将大小作为模板参数而不是函数参数。然后,它可以将模板参数传递给std::array. 文字运算符无法做到这一点。


在 C++20 中,我认为我们可以使用这样的包装类型:

template <std::size_t N>
struct helper {
    std::array<char, N> string;

    template <std::size_t... Is>
    constexpr helper(const char (&str)[N + 1], std::index_sequence<Is...>)
        :string{str[Is]...}
    {
    }
    constexpr helper(const char (&str)[N + 1])
        :helper{str, std::make_index_sequence<N>{}}
    {
    }
};

template <std::size_t N>
helper(const char (&str)[N]) -> helper<N - 1>;
Run Code Online (Sandbox Code Playgroud)

然后使用字符串文字运算符模板:

template <helper str> // placeholder type for deduction
constexpr auto operator""_S()
{
    return str.string;
}

static_assert("foo"_S == std::array{'f', 'o', 'o'});
Run Code Online (Sandbox Code Playgroud)

不过 C++20 尚未最终确定,所以我不能肯定地说。