c++ - 非模板类中的可变参数成员

标签 c++ c++11 c++14

我正在尝试编写一个类 Invocation它有一个模板化的构造函数:

template<typename F>
class Invocation {
public:
    template<typename... Args>
    Invocation(F&& f, Args&&... args)
    { /* store f and args somewhere for later use */ }

    ...
};

通常我会参数化 InvocationF 对自己进行分类和 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/

相关文章:

c++ - 如何使用自然语法实现线程安全的容器?

c++ - 如何在循环线程中使用 wait_for?

c++ - 在 C++ 中内存具有两个输入的函数

c++ - 取消引用指向数组的指针?

c++ - 没有除了风格和性能的练习?

c++ - 比较 vector 的不等式仅在 vector 元素上使用相等运算符。为什么?

c++ - 多线程代码不能使用 g++ 编译,但可以使用 clang++

c++ - 为什么在这种特殊情况下我不需要模板参数?

c++ - 如何通过计算新的 x 和 y 位置来围绕其中心旋转 Sprite ?

c++ - C++ 中的锁和互斥锁