文字运算符的模板参数列表
template parameter list for literal operator
这是我将二进制文字转换为十进制的实现:
template<char Head, char... Tail>
constexpr int operator"" _b()
{
if constexpr (sizeof... (Tail) == 0)
{
return Head - '0';
}
else
{
return (Head - '0') * (1 << sizeof...(Tail)) + operator"" _b<Tail...>();
}
}
同时 Clang fails:
prog.cc:1:2: error: template parameter list for literal operator must be either 'char...' or 'typename T, T...'
template<char Head, char... Tail>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:19:27: error: no matching literal operator for call to 'operator""_b' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template
std::cout << 110110110_b;
^
error: a literal operator template must have a template parameter list equivalent to "<char ...>"
constexpr int operator"" _b()
^
<source>(2): error C3686: 'operator ""_b': literal operator template must have exactly one template parameter that is a parameter pack
因此,icc 需要 char...
而 clang 和 msvc 需要 typename T, T...
或 char...
,只有 gcc 允许我的 Head
和 Tail
.
解决方法应该很简单——只需将 char Head, char... Tail
替换为 char... digits
和 return 一个使用 char Head, char... Tail
作为模板的新 aux
函数参数,或者使用一个结构然后专门化 head
和 head, tail...
而没有 if constexpr
.
但是我没有从标准草案中找到相关要求。你能告诉我哪个符合标准吗?当然,如果你有更优雅的解决方案(除了我上面提到的两个)不会调用编译器错误,请粘贴在这里,我将非常感激。
我不知道谁是对的,但我提出了一个 C++17 替代方案:逗号运算符和模板折叠而不是递归
template <char ... Chs>
constexpr int operator"" _b()
{
int ret {};
return ((ret <<= 1, ret += Chs - '0'), ...);
}
标准在 [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 with element type char
.
所以 GCC 允许这样做是错误的。
形式的文字运算符模板
template <class T, T... >
constexpr int operator "" _b();
是 clang 和 gcc 扩展,MSVC 不支持该扩展。
这是我将二进制文字转换为十进制的实现:
template<char Head, char... Tail>
constexpr int operator"" _b()
{
if constexpr (sizeof... (Tail) == 0)
{
return Head - '0';
}
else
{
return (Head - '0') * (1 << sizeof...(Tail)) + operator"" _b<Tail...>();
}
}
同时 Clang fails:
prog.cc:1:2: error: template parameter list for literal operator must be either 'char...' or 'typename T, T...'
template<char Head, char... Tail>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:19:27: error: no matching literal operator for call to 'operator""_b' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template
std::cout << 110110110_b;
^
error: a literal operator template must have a template parameter list equivalent to "<char ...>"
constexpr int operator"" _b()
^
<source>(2): error C3686: 'operator ""_b': literal operator template must have exactly one template parameter that is a parameter pack
因此,icc 需要 char...
而 clang 和 msvc 需要 typename T, T...
或 char...
,只有 gcc 允许我的 Head
和 Tail
.
解决方法应该很简单——只需将 char Head, char... Tail
替换为 char... digits
和 return 一个使用 char Head, char... Tail
作为模板的新 aux
函数参数,或者使用一个结构然后专门化 head
和 head, tail...
而没有 if constexpr
.
但是我没有从标准草案中找到相关要求。你能告诉我哪个符合标准吗?当然,如果你有更优雅的解决方案(除了我上面提到的两个)不会调用编译器错误,请粘贴在这里,我将非常感激。
我不知道谁是对的,但我提出了一个 C++17 替代方案:逗号运算符和模板折叠而不是递归
template <char ... Chs>
constexpr int operator"" _b()
{
int ret {};
return ((ret <<= 1, ret += Chs - '0'), ...);
}
标准在 [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 with element type
char
.
所以 GCC 允许这样做是错误的。
template <class T, T... >
constexpr int operator "" _b();
是 clang 和 gcc 扩展,MSVC 不支持该扩展。