C++11 编译时文本字符串作为模板参数

C++11 编译时文本字符串作为模板参数,c++11,variadic-templates,template-meta-programming,constexpr,string-literals,C++11,Variadic Templates,Template Meta Programming,Constexpr,String Literals,我试图将C++文字字符串转换成以下模板的实例: 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; }

我试图将C++文字字符串转换成以下模板的实例:

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)];
模板
结构字符串{
typedef字符串_常量类型;
静态constexpr const char值[sizeof…(C)]={C…};
constexpr运算符const char*(void)const{
返回值;
}
};
模板
constexpr const char string_literal::value[sizeof…(C)];
我根据各种来源提出了这些帮助程序,用于将引用的字符串值“解包”到上面的模板中

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;
};
模板
结构选择器;
模板
结构选择器{
使用type=string\u literal;
};
模板
结构解包{
使用type=typename选择器::type;
};
但是,当调用此函数时,我得到一个编译器错误:

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'>
模板
constexpr自动生成字符串文字(const char&s)[N]){
返回解包{};//此处出错
}
constexpr auto literal=make_string_literal(“测试”);
//字符串文字
GCC 4.9+报告: 错误:“const char(&s)[1]”不是类型“const char(&)[1]”的有效模板参数,因为引用变量没有常量地址

Clang 3.7.1报告: 错误:非类型模板参数引用了没有链接的对象

我尝试了几种不同的方法,但错误基本相同。
我在这里遗漏了什么?

这是满足您需求的满意解决方案吗

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
}
模板
结构字符串{
静态constexpr const char值[sizeof…(C)]={C…};
constexpr运算符const char*(void)const{
返回值;
}

void foo(){std::cout您可以使用GNU扩展()。这是目前唯一可以考虑的方法。在gcc和clang下编译的替代-不满意-解决方案:
(void)
是C-izm。
运算符const char*
当前是错误的(容易出错):您可能需要将
值的定义从
值[sizeof…(C)]={C..};
值[sizeof…(C)+1]={C..,'\0'};
,因为当前它的正确性取决于获取源字符数组的方式。需要明确的是@Orient。sizeof+1的任务是确保
运算符const char*
即使在直接实例化模板时也有空终止符(即,
)而不是从已经有空终止符的文本字符串进行初始化。我说得对吗?是的。我想是的。
字符a[3]={'1','2','3'};
也可能是这种情况。根据其他人的评论,这取决于GNU扩展(constepr用户定义的文本)这不是当前或下一个C++标准的一部分(到目前为止):