文字运算符的模板参数列表

时间:2018-12-15 02:26:23

标签: c++ language-lawyer variadic-templates template-meta-programming user-defined-literals

这是我将二进制文字转换为十进制的实现:

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...>();
    }
}

GCC compiles happily

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;
                      ^

icc also fails

error: a literal operator template must have a template parameter list equivalent to "<char ...>"

    constexpr int operator"" _b()

                  ^

MSVC also fails:

<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允许我的HeadTail

解决方法应该很简单----用char Head, char... Tail替换char... digits并返回一个新的aux函数,该函数使用char Head, char... Tail作为模板参数,或使用结构然后将headhead, tail...专门化而不使用if constexpr

但是我没有从标准草案中找到相关要求。你能告诉我哪个符合标准吗?当然,如果您有更优雅的解决方案(除了上面提到的两个解决方案),不会调用编译器错误,请粘贴在这里,我将非常感谢。

3 个答案:

答案 0 :(得分:4)

该标准在[over.literal]/5中非常明确地说明了这一点:

  

文字操作符模板的声明应具有空的参数声明子句,其模板参数列表应具有单个模板参数,该模板参数是元素类型为char的非类型模板参数包

因此,GCC允许这样做是错误的。

答案 1 :(得分:2)

我不知道谁是对的,但我提出了C ++ 17的替代方案:逗号运算符和模板折叠而不是递归

   template <char ... Chs>
   constexpr int operator"" _b()
    {
      int ret {};

      return ((ret <<= 1, ret += Chs - '0'), ...);
   }

答案 2 :(得分:1)

形式的文字运算符模板

template <class T, T... >
constexpr int operator "" _b();

是clang和gcc扩展,MSVC不支持该扩展。

但是有人提议reconsider literal operator templates