c – 基于CRTP的解决方案是什么样的?
作者:互联网
我在this帖子中询问了以下问题(为方便起见粘贴在下面).其中一条评论表明存在基于CRTP的问题解决方案.我无法弄清楚CRTP在这里是如何相关的(好吧,我之前从未使用过CRTP,所以我不习惯用这些术语来思考).那么,基于CRTP的解决方案将如何?
以下是引用的问题:
是否可以编写一个模板函数来拥有关于模板参数的基类的类型信息? (假设模板参数仅来自一个类)
所以,我正在寻找这样的事情:
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:
// https://stackoverflow.com/a/11744832/2725810
};
struct NodeData : public NodeBase {
using Base1 = NodeBase;
REFLECTABLE((double)F)
};
我想编写一个打印节点结构内容的函数. REFLECTABLE完成了提取结构字段的所有艰苦工作.但是,当用户给我一个NodeData实例时,我的函数也需要打印NodeBase组件的内容.我想稍后为两个和三个基类添加我的函数的重载.
解决方法:
要知道一个类是否从基类派生,我们有std :: is_base_of<>模板结构,可以与部分特化或std :: enable_if一起使用.
下面是使用部分专用结构来应用操作的演示,这取决于它是否从node_base派生(在这种情况下,它只打印基础对象,但您可以执行任何其他操作)
#include <iostream>
#include <type_traits>
// base class
struct node_base
{
};
std::ostream& operator<<(std::ostream& os, const node_base& nb)
{
os << "node_base_stuff";
return os;
}
// a class derived from node_base
struct node : public node_base
{
};
// a class not derived from node_base
struct not_node
{
};
// apply the general case - do nothing
template<class T, class = void>
struct report_impl
{
static void apply(const T&) {};
};
// apply the case where an object T is derived from node_base
template<class T>
struct report_impl<T, std::enable_if_t< std::is_base_of<node_base, T>::value > >
{
static void apply(const T& t) {
std::cout << static_cast<const node_base&>(t) << std::endl;
};
};
// the general form of the report function defers to the partially
// specialised application class
template<class T>
void report(const T& t)
{
report_impl<T>::apply(t);
}
using namespace std;
// a quick test
auto main() -> int
{
node n;
not_node nn;
report(n);
report(nn);
return 0;
}
预期产量:
node_base_stuff
标签:crtp,c,c11 来源: https://codeday.me/bug/20191003/1847832.html