代码之家  ›  专栏  ›  技术社区  ›  Magix

基于CRTP的多态性元件的异质收集

  •  0
  • Magix  · 技术社区  · 4 年前

    让我们承认,出于任何合理的原因,动态(虚拟)多态性对我们来说都是不可用的。CRTP提供高效的静态多态性,如下所示:

    template<typename derived_t>
    struct Base {
        void sayFoo() { std::cout << "foo" << std::endl; }
        void sayBaz() { std::cout << impl().bazWord() << std::endl; } 
            
        derived_t& impl() { return static_cast<derived_t&>(*this); }
       
    };
    
    struct derived1 : public Base<derived1> {
        std::string bazWord() { return "baz1"; }
    };
    
    struct derived2 : public Base<derived2> {
        std::string bazWord() { return "baz2"; }
    };
    

    实例化很容易完成,如下所示:

    derived1 d1;
    d1.sayFoo(); // says "foo"
    d1.sayBaz(); // says "baz1"
    
    derived2 d2;
    d1.sayFoo(); // says "foo"
    d2.sayBaz(); // says "baz2"
    

    现在,我想将这些元素保存在一个异构集合中,如下所示:

    std::vector<Base<??>> v;
    v.push_back(d1);
    v.push_back(d2);
    std::for_each(v.begin(), v.end(), [](auto& elem) { elem.sayBaz(); })
    

    这样做会给我带来一个错误,显然是因为无法定义基类型。

    有没有一种简单的方法来实现基于CRTP的异构收集?

    1 回复  |  直到 4 年前
        1
  •  0
  •   Magix    4 年前

    最简单的解决方案(但可能不是最优雅的)是使用 std::tuple 。以下示例效果良好:

    auto coll = std::make_tuple(d1, d2);
    std::apply([&](auto & ... el) { 
        (..., el.sayBaz());
    }, coll);
    

    迭代不是直截了当的,它具有 std::tuple (主要是,没有运行时插入),但至少它可以工作!