2
votes

Simplified version

class C {
 public:
 static constexpr std::array<C, 2> foo {{"1"_C, "2"_C}};
 int x;
 constexpr C(char c) { x=c; }
}
constexpr C operator"" _C(const char * str, size_t n) { return C(*str); }

This doesn't fly, because the literals are not understood at the line where the array is defined. But the free literal function can't be moved earlier because then C isn't known.

Is there a solution to this Gordian knot that doesn't involve adding variadic templates or something horrid like that into the code?

1
Variadic templates and horrid shouldn't be in the same sentence! :)GManNickG
As a side-note, I don't think _C is an allowed name, since it's underscore + uppercase letter, which is reserved for the implementation.Xeo
@Xeo: I think _C is an identifier and not a name, as talked about here, so it is okay. The name would be operator"" _C.Jesse Good
@JesseGood: GCC 4.7 and Clang 3.3 SVN do macro-expansion on the name atleast. :s With #define _C _x before the literal operator, if I do auto x = "hi"_C;, I get a compiler error, while "hi"_x works.Xeo

1 Answers

3
votes

The problem doesn't really lie with user-defined literals, but with the fact that std::array requires complete types (or really, any constexpr initialization does). The following code will also fail to compile:

#include <array>

class C {
public:
 static constexpr std::array<C, 2> foo {{C('1'), C('2')}};
 int x;
 constexpr C(char c) : x(c) {} // please use a mem-initializer-list
};

With errors similar to (Clang 3.3 SVN here):

/usr/include/c++/v1/array:136:16: error: field has incomplete type 'value_type'
      (aka 'C')
    value_type __elems_[_Size > 0 ? _Size : 1];
               ^
t.cpp:5:36: note: in instantiation of template class 'std::__1::array'
      requested here
 static constexpr std::array<C, 2> foo {{C('1'), C('2')}};
                                   ^
t.cpp:3:7: note: definition of 'C' is not complete until the closing '}'
class C {
      ^