c++ - 基于 CRTP 的解决方案会是什么样子?

标签 c++ c++11 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 完成了提取 struct 字段的所有艰苦工作。但是,当用户给我一个 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

关于c++ - 基于 CRTP 的解决方案会是什么样子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34223547/

相关文章:

c++ - QKeyEvent isAutoRepeat 不起作用?

c++ - CRTP 中的模板化派生类(奇怪的重复模板模式)

c++ - 运算符重载 : No match for 'operator[]'

c++ - 了解我有多少内存可用于动态 vector C++

c++ - 如何从 C++ 代码中获取项目名称?

c++ - 计时定时器不能正确转换秒数

c++ 整数的幂,模板元编程

c++ - 重构为模板

c++ - 函数未解析为基类重载

c++ - Boost::bind 一个带有 boost::function 参数的方法