2011-08-09 61 views
2

如何使用模板查找使用模板圖層時哪些類型是由哪些類型組成的?如何查找,由哪個模板圖層組成的對象?

讓我們

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

SFINAE可以在這裏幫助.. – Nawaz

+0

@relax - 或虛擬功能... –

回答

4

我嘗試(使用的C++ 0x功能(S))

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

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

+0

謝謝,但是當試圖在VS2010中編譯它時,我得到'error C2872:is_same:ambiguous symbol '。由於我對這種編程不是很熟悉,我無法自己修復它。你能幫我嗎? – relaxxx

+3

@relaxxx:從''刪除'using namespace std',或者刪除自定義'is_same'並使用'std :: is_same'(也可以在原始文章中使用'std :: is_base_of')。這就是爲什麼一個人不應該**寫'使用命名空間std'的方式。 –

+0

@亞歷山大謝謝你,它的作品...現在我需要一些重大的時刻了解,什麼是(拆分)...然後我會看和你的和其他答案 – relaxxx

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

編輯更好,但你只得到第一個基地。 print_type應該是遞歸的。 –

+0

@Mooing:授予。獲取類型列表並不容易,因爲VS2010沒有可變參數模板。打字模板不是你可以做的事情。 –

+0

不是'print_type (x);'工作? –

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 s在類中。如果你願意,你可以把邏輯放在printTypeComponentsImpl(或類似的東西)中,並且printTypeComponents委託給那個函數。

您可以避免創建臨時對象,但由於您不能部分專門化函數,因此必須將所有內容都移到結構中並使用它。如果你願意,我可以在這裏放置代碼示例。

編輯:如果您可以從中提取類模板的名稱(此處命名爲getTemplateName),您實際上可以使用typeid(x).name()稍微自動化一下。

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特定的例子。

+0

非常感謝您的回答 – relaxxx

1

這是一個模板unraveller,它使用可變類型名稱。你也許可以使它在VS2010的工作與通常的宏技巧(如like in the pretty-printer

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

它不會打印出任何東西令人興奮的,所以此刻的你剛剛得到每一個繼承線,但如果你partially-專門撥打printArgs您可以打印您的類型的特定信息。

+0

非常感謝您的回答 – relaxxx

相關問題