如何找到,模板层是由哪个对象组成的?

时间:2011-08-09 18:19:43

标签: c++ templates c++11 metaprogramming typetraits

如何使用模板,找出使用模板图层时由哪些类型组成的类型?

我们有

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);
}

我正在附加我的尝试,当然是错误的(仅当对象由所有测试类型组成时才有效,因为测试类型实际存在),但您可以很容易地看到它,我的目标是什么

#include <boost/type_traits/is_base_of.hpp>
#include <iostream>

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

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

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

class Blank{};

template <typename CombinedType>
void printTypeComponents(const CombinedType & t)
{
    if(boost::is_base_of<Blank, CombinedType::AComponent>::value)
        std::cout << "composed of A \n";

    if(boost::is_base_of<Blank, CombinedType::BComponent>::value)
        std::cout << "composed of B \n";

    if(boost::is_base_of<Blank, CombinedType::CComponent>::value)
        std::cout << "composed of C \n";
}

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

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

我正在使用MSVC2010

谢谢!

修改 我实际上并不对类型的名称感兴趣...我想用它来像:

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

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

4 个答案:

答案 0 :(得分:4)

我的尝试(没有使用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

答案 1 :(得分:2)

利用您的结构,如何:

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&) {}

答案 2 :(得分:1)

这可能适合你(如果我正确理解了这个问题)。我使用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委托给该函数。

您可以避免创建临时对象,但由于您无法部分专门化函数,因此您必须将所有内容移动到结构中并使用它。如果你愿意,我可以把代码示例放在这里。

编辑:您可以使用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());
}

对于那些感兴趣的人,here的gcc具体例子。

答案 3 :(得分:1)

这是一个使用可变参数类型名称的模板解析器。你可以使用通常的宏技巧(例如like in the pretty-printer)在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,你可以为你的类型打印特定的信息。