Literal compilation string as template argument

I am trying to convert a C ++ literal string to an instance of the following template:

template <char ... C> struct string_literal { typedef string_constant type; static constexpr const char value[sizeof...(C)] = {C...}; constexpr operator const char* (void) const { return value; } }; template <char ... C> constexpr const char string_literal<C...>::value[sizeof...(C)]; 

I came up with these helpers based on various sources to "unpack" the given string value into the template above.

 template <unsigned N, const char (&S) [N], typename U> struct selector; template <unsigned N, const char (&S) [N], unsigned ...I> struct selector<N, S, index_sequence<I...>> { using type = string_literal<S[I]...>; }; template <unsigned N, const char (&S) [N]> struct unpack { using type = typename selector<N, S, make_index_sequence<N>>::type; }; 

However, when I call, I get a compiler error:

 template <unsigned N> constexpr auto make_string_literal(const char (&s) [N]) { return unpack<N, s>{}; // Error here } constexpr auto literal = make_string_literal("test"); // string_literal<'t','e','s','t','\0'> 

GCC 4.9+ reports: error: 'const char (& s) [1]' is not a valid template argument for type 'const char (&) [1]' because the reference variable does not have a constant address

Clang reports 3.7.1: error: non-type template argument refers to object 'that has no binding

I tried several different approaches, but the errors are basically the same. What am I missing here?

+5
source share
1 answer

Is this a satisfactory solution to meet your needs?

 template <char ... C> struct string_literal { static constexpr const char value[sizeof...(C)] = {C...}; constexpr operator const char* (void) const { return value; } void foo() {std::cout << value << '\n';} }; template <char ... C> constexpr const char string_literal<C...>::value[sizeof...(C)]; template <typename CharT, CharT... Cs> constexpr string_literal<Cs...> operator ""_create() { return {}; } int main() { string_literal<'t','e','s','t'> s = "test"_create; std::cout << s << '\n'; // test s.foo(); // test } 
+1
source

Source: https://habr.com/ru/post/1243997/


All Articles