Zor*_*war 18 c++ templates user-defined-literals c++11
假设我有一些课程:
template <typename T>
class Foo {
const T* x_;
public:
Foo(const T* str) : x_{str} {}
};
Run Code Online (Sandbox Code Playgroud)
我提供了一些用户定义的文字来创建一个Foo对象:
Foo<char> operator"" _foo(const char* str, std::size_t) {
return Foo<char>{str};
}
Foo<wchar_t> operator"" _foo(const wchar_t* str, std::size_t) {
return Foo<wchar_t>{str};
}
// etc. for char16_t and char32_t.
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么我不能模板化这些并且不必重写代码?
template <typename T>
Foo<T> operator"" _foo(const T* str, std::size_t) {
return Foo<T>{str};
}
Run Code Online (Sandbox Code Playgroud)
gcc 5.4.0(Ubuntu 5.4.0-6ubuntu1~16.04.4)和7.0.0(自己编译)报告:
error: ‘Foo<T> operator""_foo(const T*, std::size_t)’ has invalid argument list
Foo<T> operator"" _foo(const T* str, std::size_t) {
^
Run Code Online (Sandbox Code Playgroud)
错误信息似乎很清楚,但我没有看到为什么我原则上不允许这样做的原因; 所以,我这样做不正确,还是真的不允许这样做?
sky*_*ack 15
考虑一下:
如果文字运算符是模板,则它必须具有空参数列表,并且只能有一个模板参数,该参数必须是元素类型为char的非类型模板参数包
换句话说,文字运算符模板的声明应该是:
template <char...> double operator "" _x();
Run Code Online (Sandbox Code Playgroud)
那不是你的情况.
我不是语言律师,但我想与您的案例相关的标准部分是[over.literal](链接到工作草案).
[over.literal]/2的摘录如下:
使用literal-operator-id声明的函数模板是文字运算符模板.
低于[over.literal]/5引用:
文本运算符模板的声明应具有空的parameter-declaration-clause,其template-parameter-list应具有单个模板参数,该参数是元素类型为char的非类型模板参数包([temp.variadic]) .
在我看来,该标准明确禁止与问题中的声明相似的声明.
更一般地说,声明文字运算符的函数模板必须严格遵守给定的模式.
我这样做不正确,还是真的不允许这样做?
我会说这是真的不允许的.
无论如何,如果您有不希望在每个运算符中重复的复杂逻辑,您仍然可以使用模板函数:
template<typename T>
Foo<T> create(const T *str) {
// your logic...
return Foo<T>{str};
}
Foo<char> operator"" _foo(const char *str, std::size_t) {
return create(str);
}
Foo<wchar_t> operator"" _foo(const wchar_t *str, std::size_t) {
return create(str);
}
Run Code Online (Sandbox Code Playgroud)
这是一个额外的间接层问题,就是这样.
显然,如果所有运算符都是一个行主体函数,那就不值得了.