идентификатор шаблона не соответствует ни одному объявлению шаблона - PullRequest
0 голосов
/ 25 апреля 2018

Я не уверен, почему специализация size шаблона функции для TCollection не удалась.

template <typename C>
using detect_size = decltype(std::declval<C>().size());

template <typename C>
constexpr auto size(const C& c) -> decltype(c.size()) { return c.size(); }

template <typename C>
inline std::enable_if_t<
  !is_detected<detect_size,C>::value, size_t >
size(const C& c) { return std::distance( std::begin(c), std::end(c) ); }

template <class T, size_t N>
constexpr size_t size(const T (&array)[N]) noexcept { return N; }

template <>
auto size<TCollection>(const TCollection& c) { return c.GetSize(); }

GCC дает мне

error: template-id 'size<TCollection>' for 'auto size(const TCollection&)'
does not match any template declaration

is_detected реализовано как здесь .

РЕДАКТИРОВАТЬ:

  • Если явно указать тип возвращаемого значения, ничего не изменится;
  • Если я использую перегрузку, реализация использует std::distance забирается.

Код перегрузки:

auto size(const TCollection& c) { return c.GetSize(); }

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Ответ Jarod42 только частично применим к моей ситуации.

Есть две вещи, которые я не осознавал:

  1. Специализация шаблона функции должна возвращать тот же тип, что и базовый вариант.

Точный способ определения типа возвращаемого значения не имеет значения. Итак, вместо определения, предложенного Джародом 42

template <>
std::enable_if_t<!is_detected<detect_size, TCollection>::value, size_t >
size<TCollection>(const TCollection& c) { return c.GetSize(); }

достаточно написать

template <>
size_t size(const TCollection& c) { return c.GetSize(); }
  1. Перегрузка не будет работать, если ее определение появится после вызова функции.

Если код структурирован так:

template <typename T>
size_t size(const T& x) { return x.size(); }

template <typename T>
std::vector<int> reserve_same_number_of_ints(const T& x) {
  std::vector<int> vec;
  vec.reserve(size(x));
  return vec;
}

/* specialize or overload here for special_type */

/* call reserve_same_number_of_ints on the special_type */

Специализация шаблона выбрана, но перегрузка отсутствует.

0 голосов
/ 25 апреля 2018

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

template <>
std::enable_if_t<!is_detected<detect_size, TCollection>::value, size_t >
size<TCollection>(const TCollection& c) { return c.GetSize(); }

Проще просто использовать перегрузку:

auto size(const TCollection& c) { return c.GetSize(); }

Демо

...