C++ 流畅的界面

标签 c++ fluent

我正在为我的 C++ GUI 库实现流畅的界面。基本概念是每个函数都返回一个指向模板的指针。

这里有两个类。

template <class T>
class wnd {
public:
    T* set_id(int id) { id_ = id; return (T*)this; }
    T* set_text(std::string text) { text_ = text; return (T*)this; }
protected:
    int id_;
    std::string text_;
};
    
class app_wnd : public wnd<app_wnd> {
public:
    app_wnd* show() { std::cout << text_ << " " << id_; return (app_wnd*) this; }
};

这很好用。使用 app_wnd 时,子函数返回正确的 T*,即 app_wnd*。因此我可以做 (new app_wnd())->set_id(0)->set_text("hello world")->show();

当我进行另一次推导时,问题开始了。

class main_wnd : public app_wnd {
public:
    main_wnd* set_app_instance(int instance) { instance_ = instance; return (main_wnd *) this; }
protected : 
    int instance_;
};

这个类不知道底层模板,一旦我调用 set_id() 它返回 app_wnd 类,丢失 main_wnd 的方法,即 (new main_wnd())->set_id(0)->set_app_instance (10); 将失败,因为 set_id 函数将返回 app_wnd* 而不是 main_wnd*。

是否有一个干净、漂亮、不复杂的解决方案?

最佳答案

我现在感觉年轻了一些,因为我找到了答案on Stack Exchange .需要的是使用默认模板参数的修改后的 CRTP。这是类(class)代码。

template <typename Q, typename T>
struct fluent_type {
    typedef Q type;
};

template <typename T>
struct fluent_type<void, T> {
    typedef T type;
};

template <typename T>
class wnd {
public:
    typedef typename fluent_type<T, wnd<void>>::type ftype;
    ftype* set_id(int id) { id_ = id; return static_cast<ftype*>(this); }
    ftype* set_text(std::string text) { text_ = text; return static_cast<ftype*>(this); }
protected:
    int id_;
    std::string text_;
};

template <typename T =  void>
class app_wnd : public wnd<app_wnd<T>> {
public:
    typedef typename fluent_type<T, wnd<app_wnd<T> > >::type ftype;
    ftype* show() { std::cout << text_ << " " << id_; return static_cast<ftype*>(this);
    }
};

template <typename T = void>
class main_wnd : public app_wnd<main_wnd<T>> {
public:
    typedef typename fluent_type<T, app_wnd<main_wnd<T> > >::type ftype;
    ftype* set_app_instance(int instance) { instance_ = instance; return static_cast<ftype*>(this); }
protected : 
    int instance_;
};

这里是示例调用。

auto aw = (new app_wnd<>())
    ->set_id(0)
    ->set_text("hello app_wnd")
    ->show();

auto mw = (new main_wnd<>())
    ->set_id(0)
    ->set_text("hello main_wnd")
    ->show()
    ->set_app_instance(123);

关于C++ 流畅的界面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62995665/

相关文章:

c++ - C++ 中的 Random() 效率

c++ - Lambda 只是重载了 operator() 的类?

c++ - 如何在 C++ 中输出这些符号

elasticsearch - 将SearchDescriptor放入单独的变量中,并在MultiSearch查询中使用

java - 更好的正则表达式语法想法

c# - 如何将枚举类型映射到 tinyint

c++ - 如何在编译时检查数组的大小

C++ Libzip + 删除 = 核心转储

Docker - json 文件驱动程序的工作原理

c# - 如何实现一个简单的工作流管道流畅的api方法链?