简体   繁体   中英

std::result_of for lvalue/rvalue arguments

I noticed this behavior of std::result_of when playing around:

struct Foo {
    int operator()(const int&) const { ... }
    char operator()(int&&) const { ... }
};

result_of_t<Foo(const int&)> a;  // int
result_of_t<Foo(int&&)>      b;  // char
result_of_t<Foo(int)>        c;  // char -- why?

Why does std::result_of prefer the function taking an rvalue reference for the third case?

std::result_of when given non-reference parameters presumes they are rvalues.

In fact, std::result_of_t<A(B)> is the same as std::result_of_t<A(B&&)> in almost all cases.

You can see some possibile implementations here if you want to see why. Basically, result_of_t<A(B)> does a decltype( std::declval<A>()(std::declval<B>()) ) (ignoring member function pointer cases), and a B&& rvalue reference and a temporary B will invoke the same overloads of any operator() on an A .

There are three primary value categories (lvalue, prvalue and xvalue), and three reference qualifiers (none, & and && ).

Clearly it makes sense that & should designate lvalue category and && should designate xvalue; it follows that an omitted reference qualifier should designate prvalue.

Note that this is the same as you would get for a function with the corresponding return type:

int f(); // returns prvalue int
int& f(); // returns lvalue reference to int
int&& f(); // returns xvalue reference to int

And in your case:

const int& f();
int&& g();
int h();

decltype(Foo{}(f())) a;  // int
decltype(Foo{}(g())) b;  // char
decltype(Foo{}(h())) c;  // char

So you can see that result_of is just showing what decltype would tell you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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