我正在尝试编写一个类 Invocation
它有一个模板化的构造函数:
template<typename F>
class Invocation {
public:
template<typename... Args>
Invocation(F&& f, Args&&... args)
{ /* store f and args somewhere for later use */ }
...
};
通常我会参数化 Invocation
用 F
对自己进行分类和 Args...
, 但在这种情况下,我需要一个给定的 F
的统一类型,所以我试图找到一种方法来存储 args...
Invocation<F>
中的任何类型,并尽可能减少性能损失。 (这可能不是最好的设计,但它可以是一个有趣的练习。)
一个想法是使用虚函数:
template<typename F>
class ArgsBase {
public:
// discard return value
virtual void invoke(F&& f) = 0;
};
template<typename F, typename... Ts>
class Args : public ArgsBase<F> {
public:
Args(Ts&&... args) : args_(std::forward<Ts>(args)...) {}
void invoke(F&& f) override
{
/* somehow call f with args_ (something like std::apply) */
...
}
private:
std::tuple<Ts&&...> args_;
};
然后在 Invocation<F>
类,例如我们可以有一个 std::unique_ptr<ArgsBase<F>>
成员,它指向一个 Args<F, Ts...>
在 Invocation<F>
中创建的对象 Actor 。我们可以称其为invoke
需要时使用虚方法。
这只是我想出的一个随机想法。还有其他方法可以实现这一目标吗?理想情况下没有虚函数或类似的开销?
更新:感谢建议使用 std::function
的评论/答案或 lambda。我应该明确表示我实际上对更一般的情况感兴趣,即可变参数可能不是可调用对象的参数。它可以是任何我想存储在其类型未被这些东西的类型参数化的类中的任何东西。
最佳答案
如评论中所述,我不担心按值存储参数。编译器的复制省略可能很慷慨。
特别是如果您为类提供右值调用:
#include <tuple>
template<typename F>
class ArgsBase {
public:
// discard return value
virtual void invoke(F&& f) const & = 0;
virtual void invoke(F&& f) && = 0;
};
template<typename F, class... FunctionArgs>
class Args : public ArgsBase<F> {
public:
template<class...Ts>
Args(Ts&&... args) : args_(std::forward<Ts>(args)...) {}
template<std::size_t...Is, class Tuple>
static void invoke_impl(F& f, std::index_sequence<Is...>, Tuple&& t)
{
f(std::get<Is>(std::forward<Tuple>(t))...);
}
void invoke(F&& f) const & override
{
invoke_impl(f,
std::make_index_sequence<std::tuple_size<tuple_type>::value>(),
args_);
/* somehow call f with args_ (something like std::apply) */
}
void invoke(F&& f) && override
{
invoke_impl(f,
std::make_index_sequence<std::tuple_size<tuple_type>::value>(),
std::move(args_));
/* somehow call f with args_ (something like std::apply) */
}
private:
using tuple_type = std::tuple<FunctionArgs...>;
tuple_type args_;
};
template<class Callable, class...MyArgs>
auto later(MyArgs&&...args) {
return Args<Callable, std::decay_t<MyArgs>...>(std::forward<MyArgs>(args)...);
}
void foo(const std::string&, std::string)
{
}
int main()
{
auto l = later<decltype(&foo)>(std::string("hello"), std::string("world"));
l.invoke(foo);
std::move(l).invoke(foo);
}
关于c++ - 非模板类中的可变参数成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38222029/