I know the post is old but I haven't found any solution for this problem here, and maybe someone would be interested in my workaround:
template
constexpr int string_literal_length(const char (&str)[N]) {
return N - 1;
}
template
struct string_literal {
static_assert(PassedLength == CountedLength, "Passed to STRING_LITERAL length does not match the length of string...");
};
#define STRING_LITERAL(N, str) string_literal
// ... as long as we need it ...
#define STRING_LITERAL_128(str) STRING_LITERAL_127(str), str[127]
#define STRING_LITERAL_127(str) STRING_LITERAL_126(str), str[126]
#define STRING_LITERAL_126(str) STRING_LITERAL_125(str), str[125]
#define STRING_LITERAL_125(str) STRING_LITERAL_124(str), str[124]
// ...
#define STRING_LITERAL_5(str) STRING_LITERAL_4(str), str[4]
#define STRING_LITERAL_4(str) STRING_LITERAL_3(str), str[3]
#define STRING_LITERAL_3(str) STRING_LITERAL_2(str), str[2]
#define STRING_LITERAL_2(str) STRING_LITERAL_1(str), str[1]
#define STRING_LITERAL_1(str) str[0]
Now usage:
template
struct usage_of_string_literal {
};
int main() {
usage_of_string_literal uosl;
}
Unfortunately one have to provide the length of the string to get it work but it's still more comfortable solution than plain variadic arg template of chars, and the length is verified by the static_assert so the compiler can help to pick appropriate value...
Edit
One more template magic. This one is making use of short-circuit to get rid of the string size from STRING_LITERAL declaration (c++17):
#include
#include
#define MAX_STRING_LITERAL_LENGTH 11
#define STRING_LITERAL(str) string_literal>::s
#define STRING_LITERAL_11(str) STRING_LITERAL_10(str), ((TERMINATED_10(str))?(str[10]):('\0'))
#define STRING_LITERAL_10(str) STRING_LITERAL_9(str), ((TERMINATED_9(str))?(str[9]):('\0'))
#define STRING_LITERAL_9(str) STRING_LITERAL_8(str), ((TERMINATED_8(str))?(str[8]):('\0'))
#define STRING_LITERAL_8(str) STRING_LITERAL_7(str), ((TERMINATED_7(str))?(str[7]):('\0'))
#define STRING_LITERAL_7(str) STRING_LITERAL_6(str), ((TERMINATED_6(str))?(str[6]):('\0'))
#define STRING_LITERAL_6(str) STRING_LITERAL_5(str), ((TERMINATED_5(str))?(str[5]):('\0'))
#define STRING_LITERAL_5(str) STRING_LITERAL_4(str), ((TERMINATED_4(str))?(str[4]):('\0'))
#define STRING_LITERAL_4(str) STRING_LITERAL_3(str), ((TERMINATED_3(str))?(str[3]):('\0'))
#define STRING_LITERAL_3(str) STRING_LITERAL_2(str), ((TERMINATED_2(str))?(str[2]):('\0'))
#define STRING_LITERAL_2(str) STRING_LITERAL_1(str), ((TERMINATED_1(str))?(str[1]):('\0'))
#define STRING_LITERAL_1(str) str[0]
#define TERMINATED_10(str) TERMINATED_9(str) && str[9]
#define TERMINATED_9(str) TERMINATED_8(str) && str[8]
#define TERMINATED_8(str) TERMINATED_7(str) && str[7]
#define TERMINATED_7(str) TERMINATED_6(str) && str[6]
#define TERMINATED_6(str) TERMINATED_5(str) && str[5]
#define TERMINATED_5(str) TERMINATED_4(str) && str[4]
#define TERMINATED_4(str) TERMINATED_3(str) && str[3]
#define TERMINATED_3(str) TERMINATED_2(str) && str[2]
#define TERMINATED_2(str) TERMINATED_1(str) && str[1]
#define TERMINATED_1(str) str[0]
template
struct char_pack {
static constexpr char const arr[sizeof...(Cs) + 1] = {Cs..., 0};
static constexpr std::size_t non_zero_count = (((Cs != 0)?1:0) + ...);
static_assert(non_zero_count < MAX_STRING_LITERAL_LENGTH, "You need to create more macros");
};
template
constexpr char const char_pack::arr[sizeof...(Cs) + 1];
template
constexpr std::size_t char_pack::non_zero_count;
template >
struct string_literal;
template
struct string_literal, std::enable_if_t<(Cs && ...)>, std::index_sequence> {
static constexpr char const s[sizeof...(Cs) + 1] = {Cs..., '\0'};
};
template
constexpr char const string_literal, std::enable_if_t<(Cs && ...)>, std::index_sequence>::s[sizeof...(Cs) + 1];
template
struct string_literal, std::enable_if_t, std::index_sequence>: string_literal::arr[Is]...>> { };
template
struct foo {};
int main() {
foo f;
static_cast(f);
}
[live demo]