是否可以在派生类中有选择地定义类型

时间:2011-02-10 19:56:34

标签: c++ templates

我有一个类模板,如下所示:

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,请使用其他内容,在some_type中将foo定义为int - 所以问题是,这是可能的吗? ?

我可以颠倒这种关系并为自己省去一些头痛,但在实际应用中它并不合乎逻辑......

3 个答案:

答案 0 :(得分: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;

    ...
};

答案 1 :(得分: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表达式。

答案 2 :(得分: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