如何专门化这个模板(注意返回类型)

时间:2011-01-12 04:04:04

标签: c++ templates metaprogramming

我想专注于以下模板:

template <typename T, int P>
T item(size_t s);

这样的事情:

template<int P>
T item<typename T>(size_t s)
{
//for all numeric types
    return static_cast<T>(rand());
}

template <int P>
string item<string>(size_t s)
{
    return "asdf";
}

3 个答案:

答案 0 :(得分:5)

你不能部分专门化这样的功能模板。模板部分特化仅适用于类模板。

但是,您可以使用boost::enable_if来“模拟”您正在寻找的功能模板部分特化。

// Specialization for std::string
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, std::string> >::type* = 0)
{
   ....
}

// Specialization for int
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, int> >::type* = 0)
{
    ....
}

这样,如果你调用item<5, std::string>(10),你将调用第一个函数,如果你调用item<5, int>(10),你将调用第二个函数。

或者,如果您出于某种原因不想使用Boost,另一种解决方法是创建一个调度程序类模板,当然可以部分专用。

答案 1 :(得分:1)

两者都需要部分专业化。第一个是要求SFINAE。由于函数模板只能完全专用,因此您必须使用某种类型的辅助对象。

template <typename T, int P>
T item(size_t s);

template < typename T, typename Enable = void >
struct item_
{
  template < int P >
  T apply(size_t s);
};

template < typename T >
struct item_<T, typename enable_if< is_numeric<T> >::type >
{
  template < int P >
  static T apply(size_t s) { return static_cast<T>(rand()); }
};

template < >
struct item_<std::string, void>
{
  template < int P >
  static std::string apply(size_t s) { return "NSTHEOSUNTH"; }
};

template < typename T, int P >
T item(size_t s) { return item_<T>::template apply<P>(s); }

或者您可以考虑标记调度:

struct numeric_tag {};
struct string_tag {};
struct wtf_tag {};

template < typename T, int P >
T item(size_t s, numeric_tag) { return static_cast<T>(rand()); }
template < typename T, int P >
T item(size_t s, string_tag) { return "SNTHEO"; }
template < typename T, int P >
T item(size_t s)
{
  item(s, if_
          < 
            is_numeric<T>
          , numeric_tag
          , typename if_
            <
              is_same< std::string, T >
            , string_tag
            , wtf_tag
            >::type
          >::type());
}

或者你可以混合一些元函数类来匹配标签并使用对向量...迭代通过它们测试每个(元函数类)并返回第二个(标签)来选择实现。

有很多很多方法可以解决这个问题。

答案 2 :(得分:-4)

为了清楚起见:您无法专门处理功能模板 。你可以超载它们,你不能把它们专门化。

正确绑定功能模板的部分特化(如果存在)将由以下内容给出:

template<class T, class U> X f(T,U);

specialise template<class A, class B> X f(A,B) 
  with template <class K> <K,K*>;

模板类有一个更容易的专业化规范,因为它们是由名称,函数重载唯一标识的,所以这还不够。