将CRTP与std :: tuple和可变参数模板

时间:2017-12-20 01:48:03

标签: c++ c++11 variadic-templates crtp stdtuple

我想在一些manager-class中存储任意数量的不同 类(所有共享指针)。不同的类必须从相同的CRTP接口类派生。最后,我希望能够遍历所有存储的类并调用接口的某些功能。我不想创建一个公共基类,我只想使用编译时的东西。

所以我在互联网上阅读了一些文章并一起偷了一些概念。现在我有一个可行的解决方案(我希望,我是C ++模板的新手!),但我认为,对于这样一个简单的"而言,这太过分了。需求。

你能帮助我优化(简化/缩小/修改)以下最小例子或提供更智能的解决方案吗? (没有提升,只有C ++ 11/14/17)

#include <iostream>
#include <tuple> 
#include <memory>

template <class T_IMPLEMENTATION>
struct ISystem {
    bool run(int i) { return static_cast<T_IMPLEMENTATION*>(this)->runImpl(i); }
};

struct SystemA : public ISystem<SystemA> {
    friend ISystem<SystemA>;
private:
    bool runImpl(int i) { std::cout << this << " A:" << i << std::endl; return i; };
};

struct SystemB : public  ISystem<SystemB> {
    friend ISystem<SystemB>;
private:
    bool runImpl(int i) { std::cout << this << " B:" << i << std::endl;  return i; };
};

template<typename... ARGS>
struct SystemManager {
    template <int index, typename... Ts>
    struct runSystem {
        void operator()(std::tuple<Ts...>& t, int i) {
            std::get<TUPLE_SIZE - index - 1>(t)->run(i++);
            runSystem<index - 1, Ts...>{}(t, i);
        }
    };

    template <typename... Ts>
    struct runSystem<0, Ts...>  {
        void operator()(std::tuple<Ts...>& t, int i) {
            std::get<TUPLE_SIZE - 1>(t)->run(i);
        }
    };

    template <typename...SPTR_ARGS>
    void addSystems(SPTR_ARGS...args) {
        m_tupleSystems = std::make_tuple(args...);
    }

    void run() {
        m_value = 0;
        runSystem<TUPLE_SIZE - 1, std::shared_ptr<ISystem<ARGS>>...>{}(m_tupleSystems, m_value);
    }
private:
    using TUPLE_TYPE = std::tuple<std::shared_ptr<ISystem<ARGS>>...>;
    static constexpr auto TUPLE_SIZE = std::tuple_size<TUPLE_TYPE>::value;
    TUPLE_TYPE m_tupleSystems;
    int m_value;
};

int main() {
    auto sptrSystemA = std::make_shared<SystemA>();
    auto sptrSystemB = std::make_shared<SystemB>();

    SystemManager<SystemA, SystemB> oSystemManager;
    oSystemManager.addSystems(sptrSystemA, sptrSystemB);
    oSystemManager.run();
    return 0;
}

0 个答案:

没有答案