具有每个参数类型推导的可变参数构造

发布于 2025-01-13 09:29:35 字数 2595 浏览 2 评论 0原文

我有一个类 Processor ,我希望能够使用 C++14 或更低版本(C++17、20 等想法也非常欢迎信息和子孙后代,但问题具体是 C++14):

  • 采用一个可变参数列表进行构造,其中每个元素可以是:
    • 基本上任何类型的“值”,或者
    • Handler:某种具有 do_handle 成员函数的多态类型。
  • 在内部将该异构类型列表转换为某种仅包含 Handler 的容器,使用“值”的相关“值”构造函数,并仅复制作为 Handler 传入的内容code>s
  • 稍后可以使用其他上下文进行迭代(在下面的情况下,它是一个 int,但可以是任何东西,例如其他 Processor 状态)。
// Handler base class
class Handler {
public:
    // "handle" something, somehow
    virtual int handle_thing(int foo) const = 0;
}

// Imagine there are "some" Handler derived classes of various kinds
// and say we construct by some factories which look something roughly like the following.
// Factories aren't critical, what's important is you can
// dispatch a given type to a suitable `Handler` implementation

// Factory: copy-constructs a copy of the given handler
// (may use a std::enable_if, whatever)
template<typename SomeHandler>
std::unique_ptr<Handler> make_handler(SomeHandler handler) {
   return std::make_unique<SomeHandler>(handler);
}

// Factory: create a handler for some other type
template<typename ValueType>
std::unique_ptr<Handler> make_handler(ValueType value) {
   retun std::make_unique<ValueHandler<ValueType>>(value);
}

template<typename ...Types>
class Processor {
public:
    // Some number of 
    Processor(Types&&... args) {
        // Something like this pseudo-code:
        // for (arg in args) {
        //     // Construct some suitable handler somehow
        //     m_handlers.push_back(make_handler(arg));
        // }
    }

    // use the handlers somehow (accumulation here is just an example)
    int do_process(int foo) {
        int acc = 0;
        for (const auto& handler: m_handlers) {
            acc += handler->handle_thing(foo);
        }
        return acc;
    }

private:
    // Some kind of container of per-argument handlers
    // Polymorphism probably indicates container-of-unique_ptr 
    // but not specifically needed to be so
    std::vector<std::unique_ptr<Handler>> m_handlers;
}

我的基本问题是,我不知道如何从类型 Types&&... 的异构构造参数转换为 Handler 的逐元素构造code> 基于每个元素的类型。

我尝试构造一个 std::tuple,但这似乎对我没有多大帮助,因为如何明智地迭代它并获得它并不明显生成的 Handler 容器。

我还考虑过像这样构建 m_handlers 容器:

std::vector<Handler*, sizeof...(params)> list {args...};

但是由于各个处理程序实际上是不同的类型,因此对我来说这并不明显可以完成。

I have a class Processor that I'd like to be able to, using C++14 or below (C++17, 20, etc ideas very welcome too for information and posterity, but the problem is specifically C++14):

  • Take a variadic list for construction, each element of which can be:
    • "values" of basically any type, or
    • Handlers: some kind of polymorphic type that has a do_handle member function.
  • Internally convert that heterogeneously-typed list into some kind of container of only Handlers, using the relevant "value" constructor for "values", and just copying things that come in as Handlers
  • Which can later be iterated over with some other context (in the below case it's an int, but that could be anything, e.g. other Processor state).
// Handler base class
class Handler {
public:
    // "handle" something, somehow
    virtual int handle_thing(int foo) const = 0;
}

// Imagine there are "some" Handler derived classes of various kinds
// and say we construct by some factories which look something roughly like the following.
// Factories aren't critical, what's important is you can
// dispatch a given type to a suitable `Handler` implementation

// Factory: copy-constructs a copy of the given handler
// (may use a std::enable_if, whatever)
template<typename SomeHandler>
std::unique_ptr<Handler> make_handler(SomeHandler handler) {
   return std::make_unique<SomeHandler>(handler);
}

// Factory: create a handler for some other type
template<typename ValueType>
std::unique_ptr<Handler> make_handler(ValueType value) {
   retun std::make_unique<ValueHandler<ValueType>>(value);
}

template<typename ...Types>
class Processor {
public:
    // Some number of 
    Processor(Types&&... args) {
        // Something like this pseudo-code:
        // for (arg in args) {
        //     // Construct some suitable handler somehow
        //     m_handlers.push_back(make_handler(arg));
        // }
    }

    // use the handlers somehow (accumulation here is just an example)
    int do_process(int foo) {
        int acc = 0;
        for (const auto& handler: m_handlers) {
            acc += handler->handle_thing(foo);
        }
        return acc;
    }

private:
    // Some kind of container of per-argument handlers
    // Polymorphism probably indicates container-of-unique_ptr 
    // but not specifically needed to be so
    std::vector<std::unique_ptr<Handler>> m_handlers;
}

My basic problem is that I don't know how to go from the heterogenous construction arguments of types Types&&... to an element-by-element construction of a Handler based on the type of each element.

I have tried to construct a std::tuple<Types...>, but that doesn't really seem to help me very much, since it's not obvious how to sensible iterate that and get the resulting Handler container.

I have also thought about constructing the m_handlers container like this:

std::vector<Handler*, sizeof...(params)> list {args...};

But since the individual handlers are actually different types, it's not obvious to me that that can be done.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

表情可笑 2025-01-20 09:29:35

在 C++11 和 C++14 中,您可以使用 大括号封闭初始化器 用于扩展和处理可变参数。因此,在您的情况下,您可以执行

    Processor(Types&&... args) {
        int dummy[] = { (m_handlers.push_back(make_handler(args)), 0)... };
    }

自 C++17 起,您还可以使用 折叠表达式< /a> 配合逗号操作符可以达到同样的效果:

    Processor(Types&&... args) {
        (m_handlers.push_back(make_handler(args)), ...);
    }

In C++11 and C++14 you can use brace-enclosed initializers to expand and handle variadic arguments. So in your case you could do

    Processor(Types&&... args) {
        int dummy[] = { (m_handlers.push_back(make_handler(args)), 0)... };
    }

Since C++17 you can also use a fold expression with the comma operator to achieve the same effect:

    Processor(Types&&... args) {
        (m_handlers.push_back(make_handler(args)), ...);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文