是否可以编写一个模板函数,该函数具有关于模板参数的基类的类型信息? (假设模板参数仅来自一个类)
所以,我正在寻找这样的事情:
template <class T>
auto f(T t) -> decltype(...) { // ... is some SFINAE magic that
// catches B, the base of T
std::cout << (B)t << std::endl;
}
编辑:一些相关背景。我正在编写A*
算法的通用实现。模板参数是Node
结构。因此,用户可能会定义:
struct NodeBase {
REFLECTABLE((double)g, (double)f)
// Using the REFLECTABLE macro as described here:
// http://stackoverflow.com/a/11744832/2725810
};
struct NodeData : public NodeBase {
using Base1 = NodeBase;
REFLECTABLE((double)F)
};
我想编写一个打印节点结构内容的函数。 REFLECTABLE
完成了提取struct
字段的所有艰苦工作。但是,当用户给我一个NodeData
实例时,我的函数也需要打印NodeBase
组件的内容。我想稍后为两个和三个基类添加我的函数的重载。
答案 0 :(得分:1)
您正在寻找的SFINAE东西通常是不可能的。你会为多重继承做什么?私有/受保护的继承?而且我敢打赌,我还没有考虑过更复杂的问题。我看到的唯一方法是始终使用一些反射库(而不仅仅是一个宏),您可以在其中明确定义要获取的结果。
相反,您可能正在寻找的非SFINAE和非激动方式是简单地为NodeBase
重载一次函数,然后通过(const-)引用传递派生类型:
auto f(NodeBase const& t)
{
std::cout << t << std::endl;
}
然后,调用f(NodeData{})
将自动获得对基类NodeBase
的引用。请注意,此处的引用很重要,否则您将对派生对象进行切片。
答案 1 :(得分:0)
如果你知道你的类可以继承的类型是什么,这里有一个方法来挖掘每个实例的所有实际基类。
它遵循一个最小的工作示例:
#include<type_traits>
#include<iostream>
template<int i>
struct check: check<i+1> { };
template<>
struct check<3> { };
struct B1 { };
struct B2 { };
struct B3 { };
struct D: B1, B3 { };
template<class T>
typename std::enable_if<std::is_convertible<T, B1>::value>::type
f(check<0>, T t) {
B1 b1 = static_cast<B1>(t);
std::cout << "B1" << std::endl;
f(check<1>{}, t);
}
template<class T>
typename std::enable_if<std::is_convertible<T, B2>::value>::type
f(check<1>, T t) {
B2 b2 = static_cast<B2>(t);
std::cout << "B2" << std::endl;
f(check<2>{}, t);
}
template<class T>
typename std::enable_if<std::is_convertible<T, B3>::value>::type
f(check<2>, T t) {
B3 b3 = static_cast<B3>(t);
std::cout << "B3" << std::endl;
f(check<3>{}, t);
}
template<class T>
void f(check<3>, T) {
std::cout << "end" << std::endl;
}
template <class T>
void f(T t) {
f(check<0>{}, t);
}
int main() {
D d;
f(d);
}
请注意它如何跳过涉及B2
的函数,因为它不是D
的基本类型。
如果你有超过3种类型可以继承,这个方法也很容易扩展,它不会强制使用固定的继承链,你可以对不同的类型执行不同的操作。