c ++使用CRTP为可变模板中的每种类型创建纯虚拟重载

Blu*_*ue7 1 c++ crtp template-meta-programming variadic-templates

我想为可变参数模板中的每种类型创建一个纯虚拟接口。例如,一个类:

overloads_interface<int,float,bool>
Run Code Online (Sandbox Code Playgroud)

定义了功能:

virtual void overload(const int& arg) = 0
virtual void overload(const float& arg) = 0
virtual void overload(const bool& arg) = 0
Run Code Online (Sandbox Code Playgroud)

如果我将其他类型添加到变量模板中,例如

overloads_interface<int,float,bool, std::string>
Run Code Online (Sandbox Code Playgroud)

它将自动添加重载:

virtual void overload(const std::string& arg) = 0
Run Code Online (Sandbox Code Playgroud)

然后,为了实例化此类,我必须实现这些功能,例如:

class concrete : public overloads_interface<int,float,bool> {
public:
    virtual void overload(const int& arg) override { /**handle int**/ }
    virtual void overload(const float& arg) override { /**handle float**/ }
    virtual void overload(const bool& arg) override { /**handle bool**/ }
};
Run Code Online (Sandbox Code Playgroud)

这是我创建此类的最佳尝试:

template<typename... args>
class overloads_interface {

    using param_pack = std::tuple<args...>;

    static constexpr size_t num_args = sizeof... (args);

    template<size_t i = num_args - 1>
    struct crtp : public crtp<i - 1> {
        using arg = typename std::tuple_element<i, param_pack>::type;
        using super = crtp<i - 1>;

        using super::overload; // unhide overload from super class
        virtual void overload(const arg& arg) = 0;
    };

    template<>
    struct crtp<0> {
        using arg = typename std::tuple_element<0, param_pack>::type;
        virtual void overload(const arg& arg) = 0;
    };

};
Run Code Online (Sandbox Code Playgroud)

但这无法编译:

/main.cpp:21: error: explicit specialization in non-namespace scope ‘class overloads_interface<args>’
  template<>
           ^
/main.cpp:22: error: template parameters not deducible in partial specialization:
  struct crtp<0> {
         ^~~~~~~
Run Code Online (Sandbox Code Playgroud)

并且还有一个crtp我并不真正想要的嵌套类。

我该如何上这堂课?

Kon*_*nik 8

其它的办法:

template <class T>
struct overloads_helper{
  virtual ~overloads_helper() = default;
  virtual void overload(const T&) = 0;
};

template <class... Args>
class overloads : public overloads_helper<Args>...{
};
Run Code Online (Sandbox Code Playgroud)

不知道哪个更好,是继承链还是接口的多重继承...

  • 该死的,想做同样的事情,但是有点太慢了^^。我喜欢此版本,因为它对我来说似乎更清晰。也可以只将助手隐藏在匿名名称空间中,这样就不会污染名称空间。 (2认同)