【问题标题】:C++ store functions that forward universal referencesC++ 存储转发通用引用的函数
【发布时间】:2018-03-19 10:05:12
【问题描述】:

是否可以存储与以下函数具有相似行为的函数:

void target(int foo, size_t bar) {}
void target(std::string foo, int bar) {} 

template<T...>
void forwarding_func(T&&... args)
{
    target(std::forward<T>(args)...);
}

auto forwarding_callable = ?

如何为具有与 forwarding_func 相同行为的类型 T 构建可调用对象。我必须存储它以供以后使用,所以我确实需要一个 std::function 对象吗?甚至可以在函数对象中存储像这样的 lambda 表达式吗?

auto f = [](auto&& x){
      myfunction(std::forward<decltype(x)>(x));
} 

【问题讨论】:

  • 是的,可以使用 lambda。如果你想存储它们,你可以使用std::function 或一个类,模板化在传递的 lambda 对象的类型上。
  • 可以在 std::function 对象中存储这样的东西,但不能
  • 请注意,您的示例 lambda 将(如果有效)不采用通用引用,而是采用右值引用,即。它只接受右值作为参数。我知道您明确要求如何正确执行此操作,但在我看来仍然存在一些混乱。您可能想阅读 Scott Meyer 的文章 (isocpp.org/blog/2012/11/…),了解通用引用和右值引用之间的区别。
  • "auto&& // 这里,"&&" 不代表右值引用" 他不是在这里说明 auto 也可以推导出为引用类型吗?
  • 啊,我现在明白了,auto 来自哪里...是的,你是对的,auto&amp;&amp; 将是一个通用参考,但是(你可能知道)你不能将auto 与函数参数一起使用。普通函数必须准确指定它们采用的参数类型(以及引用类型),因此没有模板就无法做到这一点。

标签: c++ lambda functional-programming


【解决方案1】:

通用引用和std::forward 仅在函数模板中有意义,因为在这种情况下,您不知道您的参数是否是左值引用。如果是,您想按原样传递它,如果不是,您想将move 传递给您要转发到的函数。这正是std::foward 所做的。 Here 很好地介绍了右值引用和完美转发。 由于非模板函数指定它们是通过值还是通过(左值)引用来获取参数,因此您可以相应地移动或不移动它们,并且不需要std::foward

由于函数模板本身并不是真正的函数,因此您不能将它们存储在 lambda 中。但是,您可以使用模板化的 operator() 创建一个仿函数:

struct Forwarding_Functor
{
    template<class... T>
    void operator()(T&&... args)
    {
        target(std::forward<T>(args)...);
    }
};

【讨论】:

    【解决方案2】:

    您需要一个函数对象,即带有operator() 的对象。该操作符应该是一个模板,并且与forwarding_func 具有相同(或相似)的签名。您可以通过多种方式构建一个。

    最直接的方法是使用 C++17 通用 lambda。如果你不能使用它,你可以定义你自己的:

    struct forwarder {
        template <typename ... Args>
           void operator()(Args&& ... args) { ... etc }
    };
    

    创建此类转发器的方式完全不同。有人提议在标准库中添加一个overload 函数。你可以这样使用它:

    auto callable = std::overload (
       (void (*)(int, size_t))(target),
       (void (*)(std::string, int))(target)
    );
    

    编译器不实现 std::overload,因为它还不是任何标准的一部分,但您可以轻松地自己实现它或在网上找到实现(例如,参见 this question)。

    【讨论】:

      猜你喜欢
      • 2021-05-26
      • 1970-01-01
      • 2012-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-24
      • 2014-06-05
      • 1970-01-01
      相关资源
      最近更新 更多