2011-02-10 98 views
2

我有一個類模板,它看起來像這樣選擇性地定義一個類型:是否有可能在派生類中

template <Base> 
struct foo : Base 
{ 
    typedef int some_type; 
}; 

,我有一個底座,看起來像這樣:

struct some_base 
{ 
    typedef float some_type; 
}; 

現在foo<some_base>::some_type將爲int,因爲衍生foo將隱藏Base::some_type。我想要做的是,如果Base::some_type已定義,請使用其他方法,在foo本地將some_type定義爲'int - 所以問題是,這可能嗎?

我可以顛倒的關係,並拯救自己有些頭痛,但它不是在實際應用中非常合乎邏輯......

回答

3

什麼是可能的有點模板元編程:)

開始通過編寫確定類型是否有一個嵌套的類型,稱爲「some_type」一元函數的。事情是這樣的:

template <typename T> 
struct has_some_type 
{ 
    typedef char no;     // type with sizeof == 1 
    typedef struct { char x[2]; } yes; // type with sizeof == 2 

    template <typename X, typename Y = typename X::some_type> 
    struct foo {}; 

    template <typename X> 
    static yes test(foo<X>*); 

    template <typename X> 
    static no test(...); 

    static const bool value = (sizeof(test<T>(0)) == sizeof(yes)); 
}; 

現在你可以做這樣的事情在派生類:

template <typename T, bool has_some_type> 
struct get_some_type; 

template <typename T> 
struct get_some_type<T, true> 
{ 
    typedef typename T::some_type type; 
}; 

template <typename T> 
struct get_some_type<T, false> 
{ 
    typedef int type; // the default type 
}; 

template <typename base> 
class derived : base 
{ 
    typedef typename get_some_type<base, has_some_type<base>::value>::type some_type; 

    ... 
}; 
+0

這正是我正在尋找的!非常感謝。 – Nim 2011-02-11 09:15:38

1

struct foo額外的模板參數默認爲int

template <Base, Typedef = int> 
struct foo : Base 
{ 
    typedef Typedef some_type; 
}; 

然後foo<some_base, some_base::some_type>::some_typesome_base::some_type

+0

只要基類型定義了`some_type`,如果它不會得到編譯器錯誤,就會工作......試試這個:`struct someother_base {};`,沒有定義`some_type`那麼上述將會失敗。 – Nim 2011-02-10 20:08:10

+0

如果沒有定義`some_base :: some_type`,則省略第二個TEmplate參數。 `foo :: some_type`將會是`int`。我的解決方案並不意味着完全自動化,但它是我能想到的唯一一個。 – Oswald 2011-02-10 20:12:56

2

這應該工作:

struct sfinae_types 
{ 
    struct yes { char x; }; 
    struct no { char x[2]; }; 
}; 

template<class T> 
class has_some_type : sfinae_types 
{ 
    private: 
    template<class U> 
    static yes test(typename U::some_type *); 
    template<class U> 
    static no test(...); 
    public: 
    enum { value = (sizeof(yes) == sizeof(test<T>(0))) }; 
}; 

template<bool, class T, typename DT> 
struct get_some_type 
{ 
    typedef DT type; 
}; 

template<class T, typename DT> 
struct get_some_type<true, T, DT> 
{ 
    typedef typename T::some_type type; 
}; 

struct B1 
{ 
}; 

struct B2 
{ 
    typedef float some_type; 
}; 

template<typename T> 
struct D : T 
{ 
    typedef typename get_some_type<has_some_type<T>::value, T, int>::type some_type; 
}; 

#include<iostream> 
#include<typeinfo> 

int main() 
{ 
    std::cout << has_some_type<B1>::value << std::endl; 
    std::cout << typeid(D<B1>::some_type).name() << std::endl; 
    std::cout << has_some_type<B2>::value << std::endl; 
    std::cout << typeid(D<B2>::some_type).name() << std::endl; 
    return(0); 
} 

,是什麼HighCommander4呈現略有變化幾秒以上...

我想boost :: mpl可能來這裏得到方便,並提供一些上面手工製作的有用的TMP表達。

相關問題