理解用户定义的字符串文字编译器错误“.. is not a variable”

flo*_*tan 6 c++ templates language-lawyer user-defined-literals c++20

我想知道这两个字符串 UDL 之间的区别。虽然第一个编译得很好,但第二个出现错误。

唯一不同的是,Literal1使用std::array作为存储,同时Literal2使用const char *

我可以轻松地Literal2显式构造一个,但是一旦我尝试使用 UDL 编译就会失败,并且'"123"' is not a valid template argument of type 'const char*' because '"123"' is not a variable. 有趣的是,如果我不在p构造函数中初始化,它也可以很好地编译。

template < size_t size >
struct Literal1 : std::array<char,size>
{
    constexpr Literal1(char const (&str)[size+1]) { for (size_t ii = 0; ii < size; ++ii) (*this)[ii] = str[ii]; }
};

template < size_t size > Literal1(char const (&str)[size]) -> Literal1<size-1>;
template < Literal1 literal > constexpr auto operator "" _lit1() { return literal; }


template < size_t size >
struct Literal2 
{
    const char* p{};

    constexpr Literal2(char const (&str)[size+1])  : p(str)  {  }
};


template < size_t size > Literal2(char const (&str)[size]) -> Literal2<size-1>;
template < Literal2 literal > constexpr auto operator "" _lit2() { return literal; }

int main() {

    constexpr auto l1 = "123"_lit1;

    constexpr auto l2 = "123"_lit2; // Compiler error....
    constexpr Literal2 l3{"123"}; // Works...
}
Run Code Online (Sandbox Code Playgroud)

有人可以解释我这里有什么区别吗?为什么 UDL 失败?

有趣的是,事实证明编译器之间也存在分歧。GCC 的行为如上所述,而 clang 抱怨这两个 UDL 定义。也许 C++ 模板 UDL 没有在 clang 中完全实现,因为我的示例基本上就是这个cppreference 页面(在最底部)上显示的内容。

现场示例在这里