从中获取基数

时间:2016-06-18 21:15:38

标签: c++ templates inheritance

假设我有一个这样的类:

template<class T>
class Base{ };

假设我有另一个类似的那样:

template<class T, class Other>
class Derived :
  public virtual Base<T>, 
  public virtual OtherRandomClass<Other> 
{ };

是否有某种方法可以创建模板类来确定Base的哪个版本(如果有的话)来自Derived这样的随机类?

2 个答案:

答案 0 :(得分:2)

这是一个可能的解决方案(从C ++ 11开始工作 - 嗯,它适用于C ++ 14,但是如果你使用Base<T>代替auto,它就可以用C ++ 11实现作为f)的返回类型:

#include<utility>
#include<type_traits>

template<class T>
class Base{ };

template<class T>
class OtherRandomClass{ };

template<class T, class Other>
class Derived :
    public virtual Base<T>, 
    public virtual OtherRandomClass<Other> 
{ };

template<typename T>
constexpr auto f(const Base<T> &b) { return b; }

template<typename T>
struct S {
    using type = decltype(f(std::declval<T>()));
};

int main() {
    static_assert(std::is_same<typename S<Derived<int, double>>::type, Base<int>>::value, "!");
}

如果DerivedBase继承多次,则无效 使用sfinae(类似于void_t惯用语),甚至可以设计一个与enable_if类似的类:只有type实际上从{{1}继承时才有T一次。
它将具有以下形式:

Base

这个结构可以在编译时用于你能想象的任何模板技巧。

在这两种情况下,template<typename T> constexpr auto f(const Base<T> &b) { return b; } template<typename...> using void_t = void; template<typename T, typename = void_t<>> struct S { }; template<typename T> struct S<T, void_t<decltype(f(std::declval<T>()))>> { using type = decltype(f(std::declval<T>())); }; (如果存在)是S::type继承的基类的类型,即Derived
有关详细信息,请参阅示例的Base<T>函数中的static_assert

答案 1 :(得分:1)

#include <iostream>
#include <typeinfo>

// placeholder template
template<class SomeDerived> struct traits {};

template<class T>
class Base{ };

template<class T>
class OtherRandomClass{ };

template<class T, class Other>
class Derived :
  public virtual Base<T>, 
  public virtual OtherRandomClass<Other> 
{ };


// specialise for our class to provide introspection
template<
  class T1, 
class T2>
struct traits<
  Derived<T1, T2>
  >
{
    using t1_type = T1;
    using first_base_type = Base<T1>;
};

int main()
{
  Derived<int, float> x;

  using mytraits = traits<decltype(x)>;
  std::cout << typeid(mytraits::t1_type).name() << std::endl;
  std::cout << typeid(mytraits::first_base_type).name() << std::endl;
}