受条件限制的模板专用化

Template specialization restricted by a condition

本文关键字:专用 条件      更新时间:2023-10-16

是否可以让编译器根据类型特征在模板规范之间进行选择?例如,考虑 Compare 函数的两个模板实现,一个用于顺序类型(string s、vector s、list s 等),另一个用于整数类型。我们可以为每个类型类只有一个模板专用化吗?

template <class SeqT>
class Compare
{
public:
   bool operator()(const SeqT& s1, const SeqT& s2) const
   {
      typename SeqT::const_iterator it1=s1.begin();
      typename SeqT::const_iterator it2=s2.begin();
      while(it1!=s1.end() && it2!=s2.end())
      {
         if(*it1<*it2) return true;
         if(*it2<*it1) return false;
         ++it1; ++it2;
      }
      return it2!=s2.end();
   }
};
template <class IntegerT>
class Compare
{
public:
   bool operator()(IntegerT i1, IntegerT i2) const
   {
      return i1<i2;
   }
};
template <class T, class Cmp = Compare<T> >
class SomeContainer
{
   ...
};

基本上,我正在寻找一种通过在模板参数上施加条件来部分专用化模板的方法。与第一Compare<>一样,专用化应应用于以下类型:std::basic_string<>std::vector<>std::list<>,第二种类型应用于以下类型:intunsignedshortchar。这可能吗?

这是我对另一个问题的回答,但这正是你需要的。它使用 SFINAE 仅为针对条件测试 true 的模板参数创建模板专用化(例如对特定类型进行检测)。

https://stackoverflow.com/a/20898554/2805305

编辑

但是,我如何才能准确地指定第一个比较专业化可以应用于例如 std::basic_string 和 std::vector?

您创建一个特征,告诉您 T 是向量还是basic_string或列表:

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <complex>
#include <type_traits>
using namespace std;
template <class T>
struct is_seq : std::false_type {
};
template <class T>
struct is_seq<std::vector<T>> : std::true_type {
};
template <class T>
struct is_seq<std::basic_string<T>> : std::true_type {
};
template <class T>
struct is_seq<std::list<T>> : std::true_type {
};
template <class T>
using enable_if_seq_type = typename std::enable_if<is_seq<T>::value>::type;
template <class T>
using enable_if_integral_type = typename std::enable_if<std::is_integral<T>::value>::type;

template <class T, class Enable = void>
class Compare; // <--------  define if you want a Compare for any type that doesn't match any specialization
template <class T>
class Compare<T, enable_if_seq_type<T>> { // specialization for T a vector, string or list
    public:
        void foo() {
            cout << "vector, string and list specialization" << endl;
        }
};
template <class T>
class Compare<T, enable_if_integral_type<T>> { // specialization for T an integral type
    public:
        void foo() {
            cout << "integral specialization" << endl;
        }
};

int main() {
    cout << std::boolalpha;
    cout << is_seq<int>::value << endl; // false
    cout << is_seq<std::vector<int>>::value << endl; // true
    Compare<int> c1; // uses second specialization
    c1.foo(); // output "integral specialization" 
    Compare<std::vector<int>> c2; // uses first specialization
    c2.foo(); // output "vector, string and list specialization"
    //Compare<std::complex<int>> c3;
    // compile error if you just declare and not define the generic Compare.
    // If you define the generic Compare, this will compile and it will use
    // that definition
    return 0;
}

http://ideone.com/JUbwla

如果希望能够实例化任何其他类型的类Compare,则定义第一个(常规)Compare声明。