Q
Q
Quad_Tree2019-03-26 10:55:12
C++ / C#
Quad_Tree, 2019-03-26 10:55:12

How to accept rvalue and lvalue arguments?

Scott Myers' book Effective C++ gives an example of such a function using the universal reference:

template<typename Container, typename Index>
decltype(auto) authAndAccess(Container&& c, Index i) {
    return std::forward<Container>(c)[i];
}

Universal reference, as I understand it, is used so that in the case of passing an lvalue, we get a link to the container, and in the case of an rvalue, we get a copy of the container. The problem is that std::forward returns a reference to the container element anyway. I.e:
decltype(auto) variable = fnt(vector<string>{"one", "two"}, 0);

The type of variable will be string& which is essentially a reference to the function's local object, resulting in SIGSEGV. How to make the function return a copy of the element in the case of an rvalue and a reference to the element if an lvalue is passed.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
F
Fil, 2019-03-26
@Fil

Universal reference allows both types of references to be passed using the reference type inference rules for the template parameter. I already wrote about forward in a comment. There is some difficulty in implementing your Wishlist in one function. Because the type of a container should affect the return type of that container. The easiest option is to write 2 overloads:

template<typename Container, typename Index>
auto authAndAccess(Container&& c, Index i) {
    return std::forward<Container>(c)[i];
}

template<typename Container, typename Index>
decltype(auto) authAndAccess(Container& c, Index i) {
    return std::forward<Container>(c)[i];
}

In the first case, we return by value, in the second - by reference.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question