是否可以自动推断函数模板的模板参数的基类?
Is it possible to auto-deduce the base class of a function template's template argument?
是否可以编写一个模板函数来拥有关于模板参数基类的类型信息?(假设模板参数仅从一个类派生)
所以,我正在寻找这样的东西:
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)
};
我想写一个函数来打印节点结构的内容。CCD_ 3完成了提取CCD_。但是,当用户给我一个NodeData
实例时,我的函数也需要打印NodeBase
组件的内容。稍后我想为两个和三个基类添加函数的重载。
您正在寻找的SFINAE内容通常是不可能的。对于多重继承,您会怎么做?私有/受保护的继承?我敢打赌,还有一些更复杂的问题我还没有想过。我看到的唯一方法是一致地使用一些反射库(而不仅仅是一个宏),在其中您可以显式地定义想要获得的结果。
相反,您可能正在寻找的非SFINAE和非令人兴奋的方法是简单地为NodeBase
重载一次函数,然后通过(const-)引用传递派生类型:
auto f(NodeBase const& t)
{
std::cout << t << std::endl;
}
调用f(NodeData{})
然后将自动获得对基类NodeBase
的引用。请注意,引用在这里很重要,否则您将对派生对象进行切片。
如果您知道类可以从哪些类型继承,这里有一个方法可以为每个实例挖掘出所有实际基类
它遵循一个最小的工作示例:
#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个以上的类型要继承,则此方法也很容易扩展,它不强制使用固定的继承链,并且可以对不同的类型执行不同的操作。
相关文章:
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 命名参数习惯用法和(抽象)基类
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- 如何允许模板参数中的类类型,仅当它有两个基类时
- 为什么我需要在成员发起器列表中重复基类的模板参数?
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- C++17 使用驱动类常量作为基类构造函数的参数来初始化基类构造函数
- 根据参数数调用 mixin 基类的构造函数
- 派生类(构造函数具有参数)和基类(构造函数缺少参数)之间没有可行的转换
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 在C++单元测试上下文中,抽象基类是否应将其他抽象基类作为函数参数
- C++ 如何使派生类自动获取基类参数
- 将派生类作为参数传递给方法,该方法是具有智能指针的基类
- 如何隐藏模板基类的参数类型
- 根据模板参数引用不同基类的函数
- 继承基构造函数,基类是模板参数 (MSVC)
- C++ 模板:重载时找不到基类类型参数方法
- 是否可以从构造函数自动推断基类模板参数?
- 如何在 C++ 中将参数传递给基类构造函数
- 如何使用 CRTP 创建具有基类的可选模板参数