Неправильное понимание шаблонов с переменными параметрами и вычитание типов шаблонов - PullRequest
0 голосов
/ 22 октября 2019

Я компилирую с C ++ 17 с кодом, похожим на этот пример:

#include <iostream>
#include <iterator>

class Foo {};

template <typename... Args,
  typename ostream_type = ::std::basic_ostream<Args...>,
  typename ostreambuf_iterator_type = ::std::ostreambuf_iterator<Args...>>
ostream_type &operator<<(ostream_type &os, const ::Foo f) {
  // Do ostreambuf_iterator_type stuff with 'f' here...
  return os;
}

int main() {
  ::Foo f;
  ::std::cout << f;

  return 0;

}

Что я обнаружил, так это то, что при применении * 1006 вывод типов шаблонов завершается неудачно* к списку параметров шаблона ostream_type и ostreambuf_iterator_type, но было бы хорошо, если бы я назначил char_type и traits_type из ostream_type.

typename ostreambuf_iterator_type = ::std::ostreambuf_iterator<typename ostream_type::char_type, typename ostream_type::traits_type>>

Почемуэто когда параметры шаблона для ::std::basic_ostream и ::std::ostreambuf_iterator совпадают?

1 Ответ

3 голосов
/ 22 октября 2019

Вывод аргумента шаблона пытается вывести ostream_type из аргумента функции. При этом он не связан указанным вами аргументом по умолчанию. Скорее аргумент по умолчанию просто игнорируется.

ostream_type будет выведен в std::basic_ostream<char>.

Тогда ничего не останется в зависимости от Args в параметрах функции, а пакет параметров будетвыводится как пустой.

Пустой Args затем раскрывается в аргумент по умолчанию ostreambuf_iterator_type = ::std::ostreambuf_iterator<Args...>, что не удается, поскольку std::ostreambuf_iterator требуется хотя бы один аргумент шаблона.

Если вы хотите Args для вывода в качестве аргументов шаблона для std::basic_ofstream, переданного вашей функции, необходимо ограничить вывод аргумента шаблона в параметре:

template <typename... Args,
  typename ostreambuf_iterator_type = ::std::ostreambuf_iterator<Args...>>
auto &operator<<(::std::basic_ostream<Args...> &os, const Foo f) {
  // Do ostreambuf_iterator_type stuff with 'f' here...
  return os;
}

Теперь вычет должен вывести Args какаргументы шаблона os.

...