2011-02-10 16 views
2

で型を定義することが可能ですfoo<some_base>::some_typeは、がBase::some_typeを隠すので、intになります。私がしたいのは、Base::some_typeが定義されている場合は、some_typefooにローカルに定義して '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

1

はそのintデフォルトstruct fooに追加のテンプレート引数を与えることができる:

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

+0

'some_base :: some_type'が定義されていない場合は、2番目のTEmplate引数を省略してください。 'foo :: some_type'は' int'になります。私の解決策は完全に自動化されることを意図したものではありませんが、私が考えることができる唯一のものです。 – Oswald

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表現。

+0

+1あなたの答えをありがとう、私は答えが最初だったと言ったように、私はHighCommander4の答えを受け入れました(?) – Nim

関連する問題