специализация типа черт - PullRequest
5 голосов
/ 10 июля 2009
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 ...

Это много дублирования ... Как я могу сохранить простоту первого бита кода, но иметь одно и то же имя класса в то же время?

Ответы [ 4 ]

5 голосов
/ 10 июля 2009

Это синтаксис частичной специализации шаблона класса:

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;
};
0 голосов
/ 10 июля 2009

Интересное замечание здесь заключается в применении наших знаний от динамического полиморфизма к полиморфизму «функция типа».

Если сравнить эту функцию 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.

0 голосов
/ 10 июля 2009
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;
};

Да, наверняка я допустил ошибку в type_t для vec3!

0 голосов
/ 10 июля 2009

Может быть, вам следует создать экземпляр шаблона с двумя типами? См:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...