reference_wrapper Referencing Primitive

2019-09-09 16:55发布

问题:

I was under the impression that I could use reference_wrapper to generate a functor that would return the object passed into the reference_wrapper ctor. But this isn't working. Am I doing it wrong? If so is there a better way to accomplish this? I can write a lambda, it just seems like I shouldn't have to.

#include <iostream>
#include <functional>
using namespace std;

void funPtrPrinter( function< int( void ) > output )
{
    cout << output() << endl;
}

int main( void )
{
    int thirteen = 13;
    auto refWrap = ref( thirteen );
    funPtrPrinter( refWrap );
}

回答1:

A similar feature exists for member variables. Maybe you confused it with that.

struct foo { int bar; };

If you have a class with public member variables, you can use std::mem_fn and std::bind to create functors returning the value of the variable.

auto f = std::mem_fn(&foo::bar);
std::cout << f(foo{42}) << '\n';

auto g = std::bind(&foo::bar, foo{42});
std::cout << g() << '\n';


回答2:

std::reference_wrapper doesn't generate functors. It is only a functor if original type is Callable - std::reference_wrapper::operator() is available only if stored reference is of callable type.

It's not clear why you need the functor at all, but if it's the case then lambda might be simplest solution.



回答3:

reference_wrapper is only callable if the object it refers to is callable. Its operator() simply calls the referenced callable object. If the object refered to is not callable then operator() does not exist. In that sense it behaves just like a "real" reference.

refWrap() would be equivalent to thirteen(), so ill formed.



回答4:

std::reference_wrapper::operator() only participates in overload resolution if it's wrapping a callable object. An int isn't one, so what you're asking for won't work.

You could do this:

int thirteen = 13;
auto refWrap = bind( [&thirteen] { return thirteen; } );
funPtrPrinter( refWrap );

Now you have a callable, the bind expression, and that can be invoked within funPtrPrinter().

If I were you, I'd skip the middleman and pass in a lambda.

int thirteen = 13;
funPtrPrinter( [&thirteen] { return thirteen; } );


回答5:

So there is a way to accomplish this using std::integral_constant:

const int thirteen = 13;
auto refWrap = bind( &std::integral_constant< int, thirteen >::operator int, std::integral_constant< int, thirteen >() );

This does solve the question, but for all intents and purposes is inferior to the lambda:

const int thirteen = 13;
auto refWrap = [=](){ return thirteen; };