我可以模板化用户定义的文字吗?
Can I template user-defined literals?
假设我有一些 class:
template <typename T>
class Foo {
const T* x_;
public:
Foo(const T* str) : x_{str} {}
};
并且我提供了一些创建 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.
我的问题是:为什么我不能将这些模板化并避免重写代码?
template <typename T>
Foo<T> operator"" _foo(const T* str, std::size_t) {
return Foo<T>{str};
}
gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) and 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) {
^
错误信息似乎很清楚,但我没有看到原则上不允许我这样做的理由;那么,我这样做是错误的,还是真的不允许这样做?
考虑 this:
If the literal operator is a template, it must have an empty parameter list and can have only one template parameter, which must be a non-type template parameter pack with element type char
换句话说,文字运算符模板的声明应该是:
template <char...> double operator "" _x();
那不是你的情况。
我不是语言律师,但我想与您的案例相关的标准部分是 [over.literal](link 工作草案)。
[over.literal]/2 的摘录如下:
A function template declared with a literal-operator-id is a literal operator template.
下面引用[over.literal]/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 ([temp.variadic]) with element type char.
在我看来,标准明确不允许与问题中的声明类似的声明。
更一般地说,声明文字运算符的函数模板必须严格遵守给定的模式。
am I doing this incorrectly, or is this genuinely not allowed?
我会说确实不允许。
无论如何,如果您有不想在每个运算符中重复的复杂逻辑,您仍然可以使用模板函数:
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);
}
这是一个额外的间接层问题,仅此而已。
很明显,如果你所有的运算符都是一行函数,那是不值得的。
假设我有一些 class:
template <typename T>
class Foo {
const T* x_;
public:
Foo(const T* str) : x_{str} {}
};
并且我提供了一些创建 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.
我的问题是:为什么我不能将这些模板化并避免重写代码?
template <typename T>
Foo<T> operator"" _foo(const T* str, std::size_t) {
return Foo<T>{str};
}
gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) and 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) {
^
错误信息似乎很清楚,但我没有看到原则上不允许我这样做的理由;那么,我这样做是错误的,还是真的不允许这样做?
考虑 this:
If the literal operator is a template, it must have an empty parameter list and can have only one template parameter, which must be a non-type template parameter pack with element type char
换句话说,文字运算符模板的声明应该是:
template <char...> double operator "" _x();
那不是你的情况。
我不是语言律师,但我想与您的案例相关的标准部分是 [over.literal](link 工作草案)。
[over.literal]/2 的摘录如下:
A function template declared with a literal-operator-id is a literal operator template.
下面引用[over.literal]/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 ([temp.variadic]) with element type char.
在我看来,标准明确不允许与问题中的声明类似的声明。
更一般地说,声明文字运算符的函数模板必须严格遵守给定的模式。
am I doing this incorrectly, or is this genuinely not allowed?
我会说确实不允许。
无论如何,如果您有不想在每个运算符中重复的复杂逻辑,您仍然可以使用模板函数:
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);
}
这是一个额外的间接层问题,仅此而已。
很明显,如果你所有的运算符都是一行函数,那是不值得的。