【问题标题】:Template type derivation模板类型派生
【发布时间】:2017-11-16 16:28:14
【问题描述】:

我需要使用模板实现一个类,比如“MyClass”。

template<class T>
class MyClass
{
public:


          T var1;
          T1 var2;
        };

有两个成员变量 var1 和 var2。如果类模板参数“T”是基本类型(例如:float、double 或 long double),变量 var1 和 var2 的类型应该与模板参数相同。即上例中的 T1 = T。

但是如果模板参数是std::complex&lt;T&gt;,我想有

T var1;
std::complex<T> var2;

C++11如何实现?

【问题讨论】:

标签: c++ c++11 templates template-specialization template-argument-deduction


【解决方案1】:

一个可能的解决方案是定义一个简单的类型特征来提取正确的类型

template <typename T>
struct myTypeTraits
 { using type = T; };

template <typename T>
struct myTypeTraits<std::complex<T>>
 { using type = T; };

MyClass 变成

template <typename T>
class MyClass
 {
   using T0 = typename myTypeTraits<T>::type;

   T0 var1;
   T  var2;
 };

如果您想确定T 是基本类型(或者您的意思是算术吗?),则要复杂一些。

一种可能的方法是定义一个类型特征来表示(truefalse)如果一个类型是 std::complex

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

template <typename T>
struct isComplex<std::complex<T>> : public std::true_type
 { };

接下来修改myTypeTraits 声明(没有泛型定义)和两个默认布尔值

template <typename T, bool = std::is_fundamental<T>::value, 
                      bool = isComplex<T>::value>
struct myTypeTraits;

接下来的两个专业,第一个用于基础知识,第二个用于复合类型

template <typename T>
struct myTypeTraits<T, true, false>
 { using type = T; };

template <typename T>
struct myTypeTraits<std::complex<T>, false, true>
 { using type = T; };

MyClass 类保持相等,但现在如果您尝试使用(例如)std::string 实例化它会报错。

以下是完整的编译示例

#include <complex>
#include <type_traits>

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

template <typename T>
struct isComplex<std::complex<T>> : public std::true_type
 { };

template <typename T, bool = std::is_fundamental<T>::value, 
                      bool = isComplex<T>::value>
struct myTypeTraits;

template <typename T>
struct myTypeTraits<T, true, false>
 { using type = T; };

template <typename T>
struct myTypeTraits<std::complex<T>, false, true>
 { using type = T; };

template <typename T>
class MyClass
 {
   public:  // public to check with the static_assert()
      using T0 = typename myTypeTraits<T>::type;

   private:
      T0 var1;
      T  var2;
 };

int main ()
 {
   MyClass<int>                  mi; // compile
   MyClass<std::complex<float>>  mc; // compile
   // MyClass<std::string>          ms; // compilation error

   static_assert( std::is_same<int, decltype(mi)::T0>{}, "!" );
   static_assert( std::is_same<float, decltype(mc)::T0>{}, "!" );
 }

【讨论】:

  • 太棒了!感谢您的回答。但是,我刚刚意识到我应该拥有再次依赖于模板参数的成员函数。您能否也为此提供优雅的解决方案?
  • @Soo - 如果你有很多不同之处,你应该考虑对整个MyClass进行部分专业化(正如昆汀建议的那样);但是如果您需要“再次依赖于模板参数的成员函数”的帮助,抱歉,它太笼统了;我建议你修改问题,用一个具体的例子,或者在另一个问题中提问。
猜你喜欢
  • 1970-01-01
  • 2011-11-19
  • 1970-01-01
  • 2018-03-30
  • 2016-02-17
  • 2015-04-10
  • 1970-01-01
  • 2021-07-25
  • 2018-06-06
相关资源
最近更新 更多