Как узнать, из каких шаблонных слоев состоит объект? - PullRequest
2 голосов
/ 09 августа 2011

Как я могу использовать шаблоны, чтобы узнать, из каких типов состоит тип, при использовании слоев шаблонов?

Давайте иметь

template <typename Super>
class A : public Super {};

template <typename Super>
class B : public Super {};

template <typename Super>
class C : public Super {};

class Blank{};

template <typename CombinedType>
void printTypeComponents(const CombinedType & t) { ... }

int main()
{
     typedef A<B<C<Blank>>> ComposedType;
     ComposedType ct;
     printTypeComponents(ct);

     typedef A<C<Blank>> ComposedType2;
     ComposedType2 ct2;
     printTypeComponents(ct2);
}

Я прилагаю свою попытку, неправильноКонечно (работает, только если объект составлен из всех протестированных типов, так как проверенные типы действительно существуют), но из этого вы можете легко увидеть, какова моя цель* Спасибо!

РЕДАКТИРОВАТЬ: На самом деле меня не интересуют имена типов ... Я хочу использовать его как:

if(composedOfA)
    doSomeCharacteristicStuffFromA(); //member function of A

if(composedOfB)
    doSomeCharacteristicStuffFromB(); //member function of B

Ответы [ 4 ]

4 голосов
/ 09 августа 2011

Моя попытка ( без с использованием функций C ++ 0x)

//----------------------------------------

struct null{};

template<typename> 
struct split
{
   typedef null Ct;
   typedef null At;
};

template<template<typename> class C, typename T> 
struct split<C<T> >
{
   typedef C<null> Ct; //class template 
   typedef T      At;  //argument type
};

template<template<typename> class C> 
struct split<C<Blank> >
{
   typedef C<null> Ct; //class template 
   typedef Blank   At;  //argument type
};

template<typename T, typename U>
struct is_same
{
   static const bool value = false;
};
template<typename T>
struct is_same<T,T>
{
   static const bool value = true;
};

typedef  A<null> anull;
typedef  B<null> bnull;
typedef  C<null> cnull;

//----------------------------------------

template <typename CombinedType>
void printTypeComponents(const CombinedType & t)
{
     typedef typename split<CombinedType>::Ct Ct;
     typedef typename split<CombinedType>::At At;

     if ( is_same<Ct,anull>::value ) 
           cout << "A" << endl;
     else if ( is_same<Ct,bnull>::value )
           cout << "B" << endl;
     else if ( is_same<Ct,cnull>::value )
           cout << "C" << endl;

     if ( !is_same<At,Blank>::value )
           printTypeComponents(At());
     else
           cout << "Blank" << endl;
}

Тестовый код:

int main()
{
     typedef A<B<C<Blank> > > ComposedType;
     ComposedType ct;
     printTypeComponents(ct);

     cout<<"-------"<<endl;

     typedef A<C<Blank> > ComposedType2;
     ComposedType2 ct2;
     printTypeComponents(ct2);
}

Выход:

A
B
C
Blank
-------
A
C
Blank

Онлайн-демонстрация: http://ideone.com/T5nD4

2 голосов
/ 09 августа 2011

Использование вашей структуры, как насчет:

template <template <typename> class X, typename T>
void print_type(const X<T>& x, char (*)[std::is_base_of<T, X<T>>::value] = 0)
{
    std::cout << "Base: " << typeid(T).name() << "\n";
    print_type<T>(x);
}

template <typename T>
void print_type(const T&) {}
1 голос
/ 09 августа 2011

Вот шаблонный разборщик, использующий различные типы названий.Вы, вероятно, можете заставить его работать в VS2010 с помощью обычных макросов (например, , как в «симпатичном принтере» .)

template <typename T> class A : public T {};
template <typename T> class B : public T {};
template <typename T> class C : public T {};

struct NullType {};


#include <tuple>
#include <iostream>

template <typename ...Args> struct Concat;

template <typename T, typename ...Args>
struct Concat<T, std::tuple<Args...>>
{
  typedef std::tuple<T, Args...> type;
};

template <typename> struct Unravel;

template <typename T, template <typename> class X>
struct Unravel<X<T>>
{
  typedef typename Concat<X<T>, typename Unravel<T>::type>::type type;
};

template <template <typename> class X>
struct Unravel<X<NullType>>
{
  typedef std::tuple<X<NullType>> type;
};

template <typename T> struct printArgs;

template <typename T, typename ...Args>
struct printArgs<std::tuple<T, Args...>>
{
  static void print() { std::cout << "Have type." << std::endl; printArgs<std::tuple<Args...>>::print(); }
};

template <typename T>
struct printArgs<std::tuple<T>>
{
  static void print() { std::cout << "Have type." << std::endl; }
};

int main()
{
  typedef A<B<C<NullType>>> CType;
  printArgs<Unravel<CType>::type>::print();
}

. Это не даст ничего захватывающего, поэтому на данный моментвы просто получаете одну строку на наследование, но если вы частично специализируете printArgs, вы можете распечатать конкретную информацию для ваших типов.

1 голос
/ 09 августа 2011

Это может сработать для вас (если я правильно понял вопрос). Я работал с gcc, но думаю, что он должен работать даже в VS2010.

void printTypeComponents(const Blank&)
{
  std::cout << "composed of Blank\n";
}

template <typename T>
void printTypeComponents(const A<T>&)
{
  std::cout << "composed of A\n";
  printTypeComponents(T());
}

template <typename T>
void printTypeComponents(const B<T>&)
{
  std::cout << "composed of B\n";
  printTypeComponents(T());
}

template <typename T>
void printTypeComponents(const C<T>&)
{
  std::cout << "composed of C\n";
  printTypeComponents(T());
}

Преимущество состоит в том, что вам не нужны никакие typedef внутри классов. Если вы хотите, вы можете поместить логику в printTypeComponentsImpl (или что-то в этом роде), и printTypeComponents делегировать эту функцию.

Вы можете избежать создания временных объектов, но, поскольку вы не можете частично специализировать функции, вам придется перемещать все внутри структуры и использовать это. Если хотите, я могу привести пример кода здесь.

edit: Вы могли бы немного автоматизировать его с помощью typeid(x).name(), при условии, что вы можете извлечь из него имя шаблона класса (здесь он называется getTemplateName).

template <template <typename> class T, typename U>
void printTypeComponents(const T<U>&)
{
  std::cout
    << "composed of "
    << getTemplateName(typeid(T<DummyClass>).name())
    << '\n';
  printTypeComponents(U());
}

Для тех, кто заинтересован, здесь конкретный пример gcc.

...