在模板化模板参数

时间:2017-07-21 13:51:24

标签: c++ c++11 templates

我正试图找到一种方法来处理一些遗留代码。有一个模板化的类,我想专门构造器在用某个参数实例化时将不同的参数传递给它的基础。

template<typename T, typename U>
class A : public U {
public:
    A(T &t, bool b);
    // Other member functions
}

template<typename T, typename U>
A<T, U>::A(T &t, bool b) 
    : U(t, b) {}

U属于某个(模板化的)类时,我需要更改此构造函数的行为。

template<typename Z>
class S;

template<typename T>
template<typename Z>
A<T, S<Z>>::A(T &t, bool b)
    : S<Z>(t, b, false) {}

这可能吗?我知道如果不重新定义新类,就无法完成类模板特化。但我宁愿只专门化这种行为,而不是这个类U的任何其他成员函数。

3 个答案:

答案 0 :(得分:0)

您可以为每个类添加一个名为id的函数,每个类的id函数返回一个不同的值。然后,您可以在传入类型的id函数时返回的内容。

答案 1 :(得分:0)

如果您不想专门研究这门课程,您可以专门教授您继承的课程:

template<typename T, typename U>
class A_impl : public U {
public:
    A_impl(T &t, bool b) : U(t, b) { }
};

template<typename T, typename Z>
class A_impl<T,S<Z> > : public S<Z> {
public:
    A_impl(T &t, bool b) : S<Z>(t, b, false) { }
};

template<typename T, typename U>
class A : public A_impl<T,U> {
public:
    using A_impl<T,U>::A_impl; // C++11 : inherit A_impl's constructor here
    A(T &t, bool b) : A_impl<T,U>(t, b) {} // or C++98 calling it
};

答案 2 :(得分:0)

C ++ 11解决方案可以基于SFINAE:如果U是基于S的类型,则启用第一个或第二个构造函数。

为了做到这一点,可以有用的开发类型特征来检测类型是否(或不是)基于S;通过例子

template <typename>
struct isS : public std::false_type
 { };

template <typename T>
struct isS<S<T>> : public std::true_type
 { };

使用isS,您可以编写构造函数(在A类的主体中),如下所示

template <typename V = U>
A(T & t, bool b,
  typename std::enable_if<false == isS<V>::value>::type * = nullptr )
   : U(t, b)
 { std::cout << "generic A constructor" << std::endl; }

template <typename V = U>
A(T & t, bool b,
  typename std::enable_if<true == isS<V>::value>::type * = nullptr)
   : U(t, b, false)
 { std::cout << "S specific A constructor" << std::endl; }

如果您需要S的模板参数,则可以按如下方式定义isS的特化

template <typename T>
struct isS<S<T>> : public std::true_type
 { using type = T; };

并将其用作typename isS<V>::type

完整的工作示例

#include <vector>
#include <iostream>
#include <type_traits>

template <typename T>
struct S
 { 
   S (T const &, bool, bool)
    { std::cout << "S constructor" << std::endl; }
 };

template <typename>
struct isS : public std::false_type
 { };

template <typename T>
struct isS<S<T>> : public std::true_type
 { };

template <typename T, typename U>
struct A : public U
 {
   template <typename V = U>
   A(T & t, bool b,
     typename std::enable_if<false == isS<V>::value>::type * = nullptr )
      : U(t, b)
    { std::cout << "generic A constructor" << std::endl; }

   template <typename V = U>
   A(T & t, bool b,
     typename std::enable_if<true == isS<V>::value>::type * = nullptr)
      : U(t, b, false)
    { std::cout << "S specific A constructor" << std::endl; }
 };

int main ()
 {
   long l { 0L };

   // print "generic A constructor"
   A<long, std::vector<int>> alv(l, true);

   // print "S constructor>" and "S specific A constructor"
   A<long, S<int>>           als(l, true);
 }