简体   繁体   English

在高阶函数中完美转发可调用对象

[英]Perfect-forwarding callable objects in higher-order functions

I had been writing higher-order functions like this: 我一直在写这样的高阶函数:

template<typename F, typename... Args>
void doStuff(F f, Args&&... args)
{
    // ...
    f(std::forward<Args>(args)...);
    // ...
}

Or maybe replace F f with F&& f . 或者用F&& f替换F f F&& f

But after I learned about ref-qualifiers (ouch), things got complicated. 但在我了解了ref-qualifiers(哎哟)之后,情况变得复杂了。 Imagine a functor class: 想象一个仿函数类:

struct Foo {
    void operator()(...) &;
    void operator()(...) &&;
};

Then my previous implementations of doStuff will only ever call the & method, since parameters are always lvalues. 然后我之前的doStuff实现只会调用&方法,因为参数总是lvalues。

I think the way to resolve this is to implement doStuff like this: 我认为解决这个问题的方法是像这样实现doStuff

template<typename F, typename... Args>
void doStuff(F&& f, Args&&... args)
{
    // ...
    std::forward<F>(f)(std::forward<Args>(args)...);
    // ...
}

This is also how std::result_of is possibly implemented . 这也是std::result_of 可能实现的方式 What I want to know is, is there any drawback to this implementation, ie, should I replace all my HOF implementations with it? 我想知道的是,这个实现有什么缺点,即我应该用它替换所有的HOF实现吗?

std::forward is a conditional r-value cast, and the point is as usual to steal the guts out of dying objects. std::forward是一个有条件的r值转换,并且这个点像往常一样从死亡对象中偷走了内脏。 There's no difference between functors and other objects in this respect. 在这方面, functors和其他对象没有区别。 The down-side is same as with any use of std::forward ; std::forward与使用std::forward ; if you are not prepared to steal those guts, you shouldn't. 如果你不准备偷走那些胆量,你就不应该。

#include <iostream>
#include <vector>

struct Foo {
    std::vector<int> vec = {1,2,3};
    std::vector<int>& operator()(...) & {
        return vec;
    }
    std::vector<int> operator()(...) && {
        return std::move(vec);
        // Clearly, don't rely on 'vec' here...
    }
};

Foo getFoo(){
    return {};
}

int main() {
    auto foo = getFoo();
    auto vec1=foo();
    auto vec2=getFoo()();
}

Clearly, don't do things like this: 显然,不要做这样的事情:

auto vec3 = std::move(foo)();
vec4 = foo();

for the same reasons. 出于同样的原因。

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

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