【问题标题】:type traits specialization类型特征专业化
【发布时间】:2009-07-10 09:49:58
【问题描述】:
template<typename T>
class vec3
{
public:
    typename T type_t;
    T x;
    T y;
    T z;
};

template<typename T>
struct numeric_type_traits_basic_c
{
    typedef T type_t;
    typedef T scalar_t;
};

template<typename T>
struct numeric_type_traits_vec3_c
{
    typedef T type_t;
    typedef typename T::type_t scalar_t;
};

typedef numeric_type_traits_basic_c<int> int_type_traits;
typedef numeric_type_traits_vec3_c< vec3<int> > vec3_int_type_traits;

这是标量和向量的类型特征,唯一的区别是向量的标量类型是其元素的类型。工作正常。

但我真的很希望能够为这两个类使用相同的名称。

template<typename T>
struct numeric_type_traits_c
{
    typedef T type_t;
    typedef ????? scalar_t;
};

我知道如果该类针对我需要的每种类型明确专门化,这是可能的:int、float、vec3、vec3...

这有很多重复...如何保持第一段代码的简单性但同时具有相同的类名?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    这是部分类模板特化的语法:

    template<typename T>
    struct numeric_type_traits // basic template
    {
        typedef T type_t;
        typedef T scalar_t;
    };
    
    template<typename T>
    struct numeric_type_traits< vec3<T> > // partial specialisation for vec3's
    {
        typedef vec3<T> type_t;
        typedef T scalar_t;
    };
    

    等等,例如:

    template <typename T, typename T_Alloc>
    struct numeric_type_traits< std::vector<T,T_Alloc> > // part. spec. for std::vector
    {
        typedef std::vector<T,T_Alloc> type_t; // deal with custom allocators, too
        typedef T scalar_t;
    };
    

    【讨论】:

      【解决方案2】:

      也许您应该使用两种类型来实例化您的模板?见:

      template<typename TYPE, typename SCALAR>
      struct numeric_type_traits_c
      {
         typedef TYPE type_t;
         typedef SCALAR scalar_t;
      };
      
      typedef numeric_type_traits_c<int,int> int_type_traits;
      typedef numeric_type_traits_c<vec3<int>, vec3<int>::type_t> vec3_type_traits;
      

      【讨论】:

      • type trait 背后的意图是避免这种情况,因为 type trait 很可能会为您提供此类信息
      【解决方案3】:
      template<typename T>
      struct numeric_type_traits_c
      {
              typedef T type_t;
              typedef T scalar_t;
      };
      
      template<typename T>
      struct numeric_type_traits_c<vec3<T> >
      {
              typedef vec3<T> type_t;
              typedef typename vec3<T>::type_t scalar_t;
      };
      

      是的,我肯定在 vec3 的 type_t 中犯了一个错误!

      【讨论】:

        【解决方案4】:

        这里有一个有趣的说法是将我们从动态多态性中获得的知识应用于“类型函数”多态性。

        如果你比较这个函数f:

        struct I { virtual double f()const = 0; }; // C++ version of 'an interface'
        struct A : public I { virtual double f()const{ return 0; } };
        struct B : public I { virtual double f()const{ return 1; } };
        struct C { };
        
        void f( const I& i ){ return I.f(); }
        
        f( A() );
        f( C() ); // compiler warning: wrong type provided.
        

        使用这个函数 f:

        // struct TI { typedef ??? iT; }; // no C++ version of a type-interface
        struct TA { typedef int iT; };
        struct TB { typedef double iT; };
        struct TC { };
        
        template< typename aTI > struct fT { typedef aTI::iT returnType; };
        
        fT< TA >::returnType vA; 
        ft< C  >::returnType vC; // compiler error: C has no iT member.
        

        您看到唯一的区别是参数的符号。第一个函数是“常规”多态函数。如果提供的参数类型不正确,编译器会警告我们。

        fT 是一个函数,只能由编译器用来确定某种类型。它需要一个类型作为参数。但是该语言没有类型约束的“概念”(但 - 请参阅 C++0x 中的概念)。所以我们需要手动保证我们用于类型函数的类型“实现”了正确的接口。

        具体来说,这归结为将scalar_t 类型添加到您想要与numeric_type_traits_c 类型函数一起使用的任何类中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-18
          • 2018-06-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多