具有每个参数类型推导的可变参数构造
Variadic construction with per-argument type deduction
我有一个 class Processor
我希望能够使用 C++14 或更低版本(C++17、20 等想法也非常欢迎提供信息和后代,但问题具体是 C++14):
- 拿一个可变列表来构造,其中的每个元素可以是:
- 基本上任何类型的“值”,或
Handler
s:某种具有 do_handle
成员函数的多态类型。
- 在内部将该异构类型列表转换为某种只有
Handler
的容器,使用“值”的相关“值”构造函数,并仅复制以 [=13= 形式出现的内容]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
的逐元素构造每个个元素。
我试图构建一个 std::tuple<Types...>
,但这似乎对我帮助不大,因为如何明智地迭代它并获得结果 Handler
容器并不明显。
我也考虑过像这样构建 m_handlers
容器:
std::vector<Handler*, sizeof...(params)> list {args...};
但是由于各个处理程序实际上是不同的类型,所以对我来说这并不明显。
在 C++11 和 C++14 中,您可以使用 brace-enclosed initializers 来扩展和处理可变参数。所以在你的情况下你可以做
Processor(Types&&... args) {
int dummy[] = { (m_handlers.push_back(make_handler(args)), 0)... };
}
从 C++17 开始,您还可以使用带逗号运算符的 fold expression 来达到相同的效果:
Processor(Types&&... args) {
(m_handlers.push_back(make_handler(args)), ...);
}
我有一个 class Processor
我希望能够使用 C++14 或更低版本(C++17、20 等想法也非常欢迎提供信息和后代,但问题具体是 C++14):
- 拿一个可变列表来构造,其中的每个元素可以是:
- 基本上任何类型的“值”,或
Handler
s:某种具有do_handle
成员函数的多态类型。
- 在内部将该异构类型列表转换为某种只有
Handler
的容器,使用“值”的相关“值”构造函数,并仅复制以 [=13= 形式出现的内容]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
的逐元素构造每个个元素。
我试图构建一个 std::tuple<Types...>
,但这似乎对我帮助不大,因为如何明智地迭代它并获得结果 Handler
容器并不明显。
我也考虑过像这样构建 m_handlers
容器:
std::vector<Handler*, sizeof...(params)> list {args...};
但是由于各个处理程序实际上是不同的类型,所以对我来说这并不明显。
在 C++11 和 C++14 中,您可以使用 brace-enclosed initializers 来扩展和处理可变参数。所以在你的情况下你可以做
Processor(Types&&... args) {
int dummy[] = { (m_handlers.push_back(make_handler(args)), 0)... };
}
从 C++17 开始,您还可以使用带逗号运算符的 fold expression 来达到相同的效果:
Processor(Types&&... args) {
(m_handlers.push_back(make_handler(args)), ...);
}