专门用于模板类的模板函数

时间:2011-08-23 19:58:05

标签: c++ templates specialization

我有一个索引器函数,并试图将它专门用于标准容器类型,但是会出错。我敢肯定它简单或不可能,但我不记得哪一个。我更喜欢这些作为一个功能对象,但我也无法做到这一点。是否可以为模板类

专门化模板函数
namespace std { //declarations of predefined indexable types
    template <class T, class A> class vector;
    //others are here too, but all have the same issue 
}
//default indexer
template <class T>
double indexer(const T& b) { //this seems to work fine
    return b.getIndex();
}
// base types
template<> double indexer<char>(const char& b) { return double(b); }
//other primitives are here too, and work fine
// standard library
template<class T, class A> 
double indexer<std::vector<T,A>>(const std::vector<T,A>& b) 
{ return b.empty() ? 0 : indexer(*b.cbegin()); } //line with error

错误消息:

error C2768: 'indexer' : illegal use of explicit template arguments

我希望这是专门化和重载,因为我有一个函数A,它接受​​一个函数对象/指针模板参数,以及重载函数A,它调用带有默认值的第一个A索引器。

template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>);} //default wrapper

这似乎很可能是一个重复的问题,但我似乎找不到一个。

3 个答案:

答案 0 :(得分:2)

您不能部分专门化模板功能,只能模板化类。

改为使用重载:

namespace std { //declarations of predefined indexable types
       template <class T, class A> class vector;
}
//default indexer
template <class T>
double indexer(const T& b) { return b.getIndex(); }

double indexer(const char& b) { return double(b); }

template<class T, class A>
double indexer(const std::vector<T,A>& b)
{ return b.empty() ? 0 : indexer(*b.cbegin()); }

答案 1 :(得分:1)

由于函数不能部分专用,我可以用函数对象替换索引器函数。这似乎工作正常,并解决了我所有的问题。

namespace std { //declarations of predefined indexable types
    template <class T, class A> class vector;
}
template <class T>
struct indexer { 
    double operator()(const T& b) const 
    { return b.getIndex(); } 
};
template<> struct indexer<char> { 
    double operator()(const char& b) const 
    { return double(b); } 
};
template<class T, class A> struct indexer<std::vector<T,A>> { 
    double operator()(const std::vector<T,A>& b) const 
    { return b.empty() ? 0 : indexer(*b.cbegin()); } 
};

template<class T, class function>
double A(T a, function F) { return F(a);} //complicated
template<class T>
double A(T a) {return A(a, indexer<T>());} //default wrapper

答案 2 :(得分:0)

这是一个完全基于重载的解决方案,使用C ++ 11风格的可变参数模板:

template <typename T>
T print(const T & t)
{
  std::cout << t << std::endl;
  return t;
}

template <template <typename...> class Container, typename ...Args>
typename Container<Args...>::value_type print(const Container<Args...> & v)
{
  typedef typename Container<Args...>::value_type T;

  if (v.empty()) std::cout << "nil" << std::endl;
  else std::cout << *v.begin() << std::endl;

  return v.empty() ? T() : *v.begin();
}

如果您想要花哨,并且您有权访问is_container类型特征(例如从pretty printer获取),则可以使用{{1}使容器超载特定于容器}:

enable_if