Соответствует ли расширение пустого пакета значений типу пакета или необязательному параметру типа? - PullRequest
5 голосов
/ 29 февраля 2012

Я просто пытался взломать двоичный литерал operator ""_b, но застрял, пытаясь прекратить рекурсию.Как определить функцию, которую можно вызывать, используя пустой явный список параметров шаблона, который не конфликтует с перегрузкой пакета параметров?Затем вдохновение: сопоставьте расширение пустого пакета с чем-то дурацким.

Но GCC жалуется, что несуществующие типы пустого списка аргументов не согласуются с явно не обязательными типами списка параметров.Должно ли это работать таким образом?

template< char head, char ... tail >
constexpr unsigned long long parse_binary() {
    return ( ( head - '0' ) << sizeof ... (tail) )
        + parse_binary< tail ... >(); // Error: no overload for termination.
}

template< typename = void > // I want this to match an empty pack of chars.
// template< short = 0 > // even this would do.
constexpr unsigned long long parse_binary() {
    return 0;
}

template< char ... digits >
constexpr unsigned long long operator ""_b() {
    return parse_binary< digits ... >();
}

#include <iostream>

int main() {
    std::cout << 010101_b << '\n';
}

Примечание. Вопрос не реализует operator ""_b.Эта проблема может быть решена путем расширения пакета в список параметров и передачи std::integral_constant типов вокруг.

Примечание 2: Этот код на самом деле работает с незначительной корректировкой;см. мой ответ ниже.Но это не решает вопрос напрямую.Хм, может быть, я должен был отредактировать это вместо ответа…

Ответы [ 2 ]

4 голосов
/ 29 февраля 2012

Не лучше ли прекратить рекурсию одним персонажем?

template<char Ch>
constexpr unsigned long long parse_binary(){
  return Ch - '0';
};

// second head to disambiguate
template< char head1, char head2, char ... tail >
constexpr unsigned long long parse_binary() {
    return ( ( head1 - '0' ) << sizeof ... (tail)+1 ) + parse_binary< head2, tail ... >();
}

В любом случае, проблема в том, что parse_binary для нулевых символов необходимо объявить до версии с вариадическим кодом, как замечательно отмечает Кланг:

error: call to function 'parse_binary' that is neither visible in
      the template definition nor found by argument-dependent lookup

// call trace...

note: 'parse_binary' should be declared prior to the call site
      constexpr unsigned long long parse_binary() {
0 голосов
/ 29 февраля 2012

Нет официального слова о соответствии такого хитрого соответствия, но данный код работает , если две перегрузки транспонированы.

Вторая, завершающая перегрузка не видна первой, поскольку первая разрешает имя во время определения шаблона. Только вызовы функций, зависящие от параметра шаблона, имеют задержку поиска до времени создания экземпляра.

Просто чтобы прояснить, это работает :

template< typename = void > // Define this one first!
constexpr unsigned long long parse_binary() {
    return 0;
}

template< char head, char ... tail >
constexpr unsigned long long parse_binary() {
    return ( ( head - '0' ) << sizeof ... (tail) )
        + parse_binary< tail ... >(); // Bingo: overload found.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...