template-id与任何模板声明都不匹配

时间:2018-04-25 07:51:42

标签: c++ templates template-specialization

我不确定为什么size的{​​{1}}函数模板的特化失败。

TCollection

GCC给了我

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(); }

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

编辑:

  • 明确指定返回类型不会改变任何内容;
  • 如果我使用重载,则会使用is_detected进行实现。

重载代码:

std::distance

2 个答案:

答案 0 :(得分:0)

您必须使用完全相同的通用模板声明进行专业化,因此:

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(); }

Demo

答案 1 :(得分:0)

Jarod42的答案仅部分适用于我的情况。

有两件事我没有意识到:

  1. 函数模板特化必须返回与基本情况相同的类型。
  2. 拼写返回类型的确切方式并不重要。所以,而不是Jarod42建议的定义

    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. 如果在函数调用后出现定义,则过载无效。
    2. 如果代码的结构如下:

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

      拾取模板专精,但不会超载。