Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 受条件限制的模板专门化_C++_Templates_Specialization - Fatal编程技术网

C++ 受条件限制的模板专门化

C++ 受条件限制的模板专门化,c++,templates,specialization,C++,Templates,Specialization,是否可以让编译器根据类型特征在模板规范之间进行选择?例如,考虑比较函数的两个模板实现,一个是顺序类型( String > s,向量 s,列表 s),另一个是整数类型。对于每个类型的类,我们只能有一个模板专门化吗 template <class SeqT> class Compare { public: bool operator()(const SeqT& s1, const SeqT& s2) const { typename SeqT::

是否可以让编译器根据类型特征在模板规范之间进行选择?例如,考虑比较函数的两个模板实现,一个是顺序类型(<代码> String <代码> > s,<代码>向量 s,<代码>列表 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
{
   ...
};
模板
班级比较
{
公众:
布尔运算符()
{
typename SeqT::const_迭代器it1=s1.begin();
typename SeqT::const_迭代器it2=s2.begin();
而(it1!=s1.end()&&it2!=s2.end())
{

if(*it1这是我对另一个问题的回答,但这正是您所需要的。它使用SFINAE仅为测试条件为true的模板参数创建模板专门化(如being特定类型)

编辑

但是,我如何确切地指定第一个比较专门化可以应用于例如std::basic_字符串和std::vector

您创建一个特征,告诉您T是向量还是基本字符串或列表:

#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
模板
结构是_seq:std::false_类型{
};
模板
结构是_seq:std::true_类型{
};
模板
结构是_seq:std::true_类型{
};
模板
结构是_seq:std::true_类型{
};
模板
使用enable_if seq_type=typename std::enable_if::type;
模板
使用enable_if_integral_type=typename std::enable_if::type;
模板

类比较;//是的。如果我首先想到了
std::enable\u,那么请查看std::enable\u,但我认为最好添加一个模板参数,该参数指示类型的类型,并且可以通过TMP“计算”从基本类型开始。然后只提供专门化。你所说的序列是什么意思?你是指任何可以使用for(auto x:y)的
进行迭代的对象吗
syntax?谢谢。但是我如何确切地指定第一个比较专门化可以应用于例如std::basic_string和std::vector?另外,我不需要编译失败,但编译器需要在类型参数匹配某些条件时选择适当的模板。因此,就像上面的示例中一样,如果某个容器被实例化ed,然后使用Compare,如果SomeContainer被实例化,那么使用Compare。@bolov上述方法有一个问题。简单的问题是,带有异常分配器的
std::vector
、带有非默认字符特征的
std::string
等都不起作用。根本的问题是维护
模板的列表与进行某种duck类型测试相比,匹配条件的类型通常是一个坏主意。@bolov感谢代码示例!我现在可以更好地理解类型启用码的概念了。@Yakk您在模板声明中对默认类型提出了一个非常重要的观点。使用类型构造可能不是普遍可以接受的ned模板专门化。