是否可以根据类型特征使编译器在模板规范之间进行选择?例如,考虑比较功能的两个模板实现,一个用于顺序类型(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<>
,以及以下类型的第二个:int
,{ {1}},unsigned
,short
。这可能吗?
答案 0 :(得分:2)
这是我对另一个问题的回答,但这正是你所需要的。它仅使用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;
}
如果您希望能够为任何其他类型实例化类Compare
,那么您可以定义第一个(常规)Compare
声明。