问题描述
我在信息中提出了以下问题(为方便起见,请在下面粘贴)。其中一个意见认为,有一个基于CRTP的解决方案。我不能弄清楚CRTP是如何相关的(好吧,我从来没有使用过CRTP,所以我不习惯这些术语)。
I asked the following question in this post (pasted below for convenience). One of the comments suggested that there is a CRTP-based solution to the problem. I am not able to figure out how CRTP is relevant here (well, I never used CRTP before, so I am not used to thinking in these terms). So, how would a CRTP-based solution look like?
这是引用的问题:
它是一个基于CRTP的解决方案可能写一个模板函数,它将拥有模板参数的基类的类型信息? (假设模板参数只来自一个类)
Is it possible to write a template function that would possess type information about the base class of the template argument? (assuming that the template argument derives from one class only)
所以,我在寻找这样的东西:
So, I am looking for something like this:
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
结构。因此,用户可以定义:
Some relevant background: I am writing a generic implementation of the A*
algorithm. The template argument is a Node
structure. So, the user might define:
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
组件的内容。我想稍后为两个和三个基类添加我的函数的重载。
I would like to write a function that prints the contents of the node structure. REFLECTABLE
does all the hard work of extracting the fields of the struct
. However, when the user gives me a NodeData
instance, my function needs to print the contents of the NodeBase
component as well. I would like to later add overloads of my function for two and three base classes.
推荐答案
基类我们有std :: is_base_of<>模板结构,它可以与部分专门化或std :: enable_if结合使用。
to know whether a class derives from a base class we have the std::is_base_of<> template structure, which can be used in conjunction with partial specialisation, or std::enable_if.
这是一个演示使用部分专用的结构来应用一个操作取决于它是从node_base派生的(在这种情况下,它只打印基础对象,但你可以做任何其他操作)
Here is a demonstration of using a partially specialised structure to apply a an operation depending on whether it's derived from node_base or not (in this case, it just prints the base object but you could do any other operation)
#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的解决方案是什么样子的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!