Список параметров шаблона для литерального оператора
Вот моя реализация преобразования двоичного литерала в десятичный:
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 терпит неудачу:
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...
в то время как лязг и 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 ответа
В стандарте это четко изложено в [over.literal] / 5:
Объявление шаблона литерального оператора должно иметь пустое предложение-объявление-параметра, а его список-параметра-шаблона должен иметь единственный шаблон-параметр, который представляет собой нетипизированный пакет параметров шаблона с типом элемента
char
,
Таким образом, GCC не прав в этом разрешении.
Я не знаю, кто прав, но я предлагаю альтернативу C++17: оператор запятой и свертывание шаблона вместо рекурсии
template <char ... Chs>
constexpr int operator"" _b()
{
int ret {};
return ((ret <<= 1, ret += Chs - '0'), ...);
}
Шаблон буквального оператора формы
template <class T, T... >
constexpr int operator "" _b();
является расширением clang и gcc, MSVC не поддерживает это расширение.
Было, однако, предложение пересмотреть шаблоны литеральных операторов.