Understanding user-defined string literal compiler error ".. is not a variable"

74 Views Asked by At

I'm wondering about the difference between these two string UDLs. While the first one is compiling nicely, I get an error with the second one.

The only difference is that Literal1 uses std::array as storage, while Literal2 uses const char *.

I can easily construct a Literal2 explicitly, but as soon as I try and use the UDL compilation fails with '"123"' is not a valid template argument of type 'const char*' because '"123"' is not a variable. Interestingly, it also compiles nicely if I do not initialize p in the constructor.

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...
}

Can anybody explain me what's the difference here? Why is the UDL failing?

Interestingly, it turns out that there is also disagreement among compilers. GCC behaves as described above, while clang complains about both of the UDL definitions. Perhaps the C++ template UDL is not fully implemented in clang, because my example is basically what is shown on this cppreference page (at the very bottom).

Live example here.

0

There are 0 best solutions below