2
votes

I've tried the following code in GCC 4.8:

#include <iostream>
using namespace std;

template <typename T, T... vs>
struct integral_list {
    typedef T elem_type;
};
template <typename T, T... vs> 
struct gen_array {
    static const T data[sizeof...(vs)];
};
template <typename T, T... vs> 
const T gen_array<T, vs...>::data[sizeof...(vs)] = { vs... };

template <char... cs>
constexpr auto operator "" _lit() -> integral_list<char, cs...> {
    return declval<integral_list<char, cs...>>();
}

int main() {
    int (& data)[4] = gen_array<char, decltype("abcd"_lit)>::data;
    for (int i = 0; i < 4; ++i)
        cout << data[i] << endl;
}

and got

tester.cpp:21:48: error: unable to find string literal operator 'operator"" _lit' with 'const char [5]', 'unsigned int' arguments

while C++11 Standard says

13.5.8.5: The declaration of a literal operator template shall have an empty parameter-declaration-clause and its template-parameter-list shall have a single template-parameter that is a non-type template parameter pack (14.5.3) with element type char.

So either I didn't figure out the line of standard or GCC goes weird. Could you help me solving this dilemma? If not, is there any other way to implement a conversion of string literal to variadic template's argument list?

2

2 Answers

3
votes

You cannot use literal operator templates with string literals, only with numeric literals.

ยง 2.14.8 para 5:

If L is a user-defined-string-literal, let str be the literal without its ud-suffix and let len be the number of code units in str (i.e., its length excluding the terminating null character). The literal L is treated as a call of the form

operator "" X (str , len)

Nonetheless, it is possible to do some compile-time computations with the argument string. Trivial example, possibly useful as a model:

#include <iostream>

constexpr unsigned long operator"" _mylong(const char* s, size_t l) {
  return l == 0 ? 0UL : (s[l - 1] - '0') + 10 * operator"" _mylong(s, l - 1);
}

int main() {
  std::cout << "1492888888888888"_mylong << std::endl;
  return 0;
}
2
votes

In gcc 4.9 it is available (you will probably need compile it form SVN)

http://gcc.gnu.org/ml/gcc-patches/2013-04/msg00998.html