список параметров шаблона для литерального оператора - PullRequest
0 голосов
/ 15 декабря 2018

Вот моя реализация преобразования двоичного литерала в десятичную:

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 компилируется счастливо ,

, в то время как Clang завершается ошибкой :

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 также не работает :

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

    constexpr int operator"" _b()

                  ^

MSVC также не работает:

<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 и вернуть новую функцию aux, которая использует char Head, char... Tail в качестве параметров шаблона, или использовать структуру, затем специализировать head и head, tail... без if constexpr.

Но я не нашел связанныхтребование от стандартного проекта.Можете ли вы сказать мне, какой из них соответствует стандарту?Конечно, если у вас есть более элегантное решение (помимо двух, о которых я упоминал выше), которое не вызовет ошибок компилятора, вставьте его сюда, я буду очень признателен.

Ответы [ 3 ]

0 голосов
/ 15 декабря 2018

Стандарт гласит это довольно явно в [over.literal] / 5 :

Объявление шаблона литерального оператора должно иметь пустой параметр-объявление-предложениеи его список параметров шаблона должен иметь единственный шаблонный параметр, который является нетиповым пакетом параметров шаблона с типом элемента char.

Так что GCC ошибается, допуская это.

0 голосов
/ 15 декабря 2018

Литеральный шаблон оператора в форме

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

является расширением clang и gcc, MSVC не поддерживает это расширение.

Было, однако, предложение пересмотреть литералшаблоны операторов

0 голосов
/ 15 декабря 2018

Я не знаю, кто прав, но я предлагаю альтернативу C ++ 17: оператор запятой и свертывание шаблона вместо рекурсии

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

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