简体   繁体   English

C ++存储功能可转发通用引用

[英]C++ store functions that forward universal references

Is it possible to store a function that has similar behaviour to the following function: 是否可以存储与以下功能具有相似行为的功能:

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 = ?

How would one build the callable object for types T that has the same behaviour as the forwarding_func. 对于具有与forwarding_func相同行为的类型T,如何构建可调用对象。 I have to store it for later use, so I do need a std::function object? 我必须存储它以备后用,所以我确实需要一个std :: function对象吗? Is it possible to even store lambdas like these in function objects? 是否可以在函数对象中存储像这样的lambda?

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

You need a function object, that is, one with operator() . 您需要一个函数对象,即一个带有operator() This operator should be a template and have the same (or similar) signature as forwarding_func . 该运营商应该是一个模板,具有相同(或相似)的签名forwarding_func You can build one in a variety of ways. 您可以通过多种方式构建一个。

The most straightforward way is to use C++17 generic lambda. 最直接的方法是使用C ++ 17通用lambda。 If you can't use that, you can define your own: 如果您不能使用它,则可以定义自己的:

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

There is a completely different way to create such forwarders. 创建此类转发器的方式完全不同。 There is a proposal to add an overload function to the standard library. 建议将overload函数添加到标准库中。 You would use it like this: 您可以这样使用它:

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

Compilers don't implement std::overload as it isn't a part of any standard yet, but you can easily implement it yourself or find an implementation on the net (see this question for example). 编译器尚未实现std :: overload,因为它尚未成为任何标准的一部分,但您可以自己轻松实现它,也可以在网上找到实现(例如,请参阅此问题 )。

Universal references and std::forward only make sense in function templates, as in this case you don't know whether your argument is an lvalue-reference or not. 通用引用和std::forward仅在函数模板中有意义,因为在这种情况下,您不知道您的参数是否为左值引用。 If it is, you want to pass it on as is, if not, you want to move it into the function you're forwarding to. 如果是,则希望按原样传递它;如果不是,则想move其移至要转发到的函数中。 That is exactly what std::foward does. 这正是std::foward所做的。 Here 'sa very nice introduction to rvalue-references and perfect forwarding. 这里是有关右值引用和完美转发的很好的介绍。 As non-template functions specify whether they take their arguments by value or by (lvalue-)reference, you can just move or not move them accordingly and don't need std::foward . 由于非模板函数指定它们是通过值还是通过(lvalue-)引用接受参数,因此您可以相应地移动或不移动它们,而无需std::foward

As function templates are not actually functions themselves, you cannot store them in a lambda. 由于功能模板本身并不是实际的功能,因此无法将其存储在lambda中。 You can however create a functor with a templated operator() : 但是,您可以使用模板化的operator()创建函子:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM