简体   繁体   中英

template-id does not match any template declaration

I'm not sure why specialization of the size function template for TCollection fails.

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 gives me

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

is_detected is implemented as here .

EDIT:

  • Specifying return type explicitly doesn't change anything;
  • If I use overloading, the implementation using std::distance gets picked up.

Overload code:

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

You have to use the exact same declaration of your generic template for your specialization, so:

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

Simpler is to use overload:

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

Demo

Jarod42's answer is only partially applicable to my situation.

There are two things I didn't realize:

  1. Function template specialization must return the same type as the base case.

The exact way the return type is spelled out is not important. So, instead of the definition suggested by Jarod42

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

it suffices to write

template <>
size_t size(const TCollection& c) { return c.GetSize(); }
  1. The overload won't work if it's definition appears after the function call.

If the code is structured like this:

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 */

A template specialization is picked up, but an overload is not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM