如何使用模板,找出使用模板图层时由哪些类型组成的类型?
我们有
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
答案 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
答案 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
,你可以为你的类型打印特定的信息。