2011-02-10 99 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表达。

相关问题