假设我有一个这样的类:
template<class T>
class Base{ };
假设我有另一个类似的那样:
template<class T, class Other>
class Derived :
public virtual Base<T>,
public virtual OtherRandomClass<Other>
{ };
是否有某种方法可以创建模板类来确定Base
的哪个版本(如果有的话)来自Derived
这样的随机类?
答案 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, "!");
}
如果Derived
从Base
继承多次,则无效
使用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;
}