c++c++17lvalue

Candidate function not viable: expects an l-value for 1st argument


I'm trying to write a function that I can compose like this doIt(doIt(x, y), z) but I am running into the error: candidate function not viable: expects an l-value for 1st argument.

Here is my implementation.

auto doIt(std::list<std::map<int, std::any>>& x, std::list<std::map<int, std::any>>& y) {
    std::list<std::map<int, std::any>> z(x);
    
    return z;
}

Here are some data that I want to pass in.

std::list<std::map<int, std::any>> x = {
    {{0, 1}, {-1, 0.5f}},
    {{0, 0}, {-1, 0.5f}}
};

std::list<std::map<int, std::any>> y = {
    {{0, 1}, {1, 1}, {-1, 0.5f}},
    {{0, 1}, {1, 0}, {-1, 0.5f}},
    {{0, 0}, {1, 1}, {-1, 0.4f}},
    {{0, 0}, {1, 0}, {-1, 0.6f}},
};

std::list<std::map<int, std::any>> z = {
    {{0, 1}, {1, 1}, {-1, 0.5f}},
    {{0, 1}, {1, 0}, {-1, 0.8f}},
    {{0, 0}, {1, 1}, {-1, 0.5f}},
    {{0, 0}, {1, 0}, {-1, 0.6f}},
};

When I invoke the method as follows, I get no error.

auto _t = doIt(x, y);
_t = doIt(_t, y);

However, what I really want to do is the following.

auto _t = doIt(doIt(x, y), z);

Attempting to do the above gives me this error in Jupyter Notebook (xeus-cling C++17 kernel).

input_line_23:2:2: error: no matching function for call to 'doIt'
 doIt(doIt(x, y), z)
 ^~~~
input_line_12:1:6: note: candidate function not viable: expects an l-value for 1st argument
auto doIt(std::list>& x, std::list>& y) {
     ^

I see a lot of other posts, but none of them helped me. I also searched but there was too much theory behind what was being explained. Any help is appreciated.

Based on the comments below (accepted answer), the code has been revised as follows and works.

using _item = std::list<std::map<int, std::any>>;

auto doIt(const _item& x, const _item& y) {
    std::list<std::map<int, std::any>> z(x);
    
    return z;
}

Solution

  • doIt(x, y) returns a temporary, so you can't bind a non-const reference to it, which is what you are trying to do when you pass it as the first parameter to doit(..., z). Declaring that parameter as a const reference fixes that:

    auto doIt(const std::list<std::map<int, std::any>>& x, ...
              ^^^^^
    

    The same applies to other parameters that you don't write to. And, your code is crying out for a using declaration instead of repeating std::list<std::map<int, std::any>> all over the place.

    Also, why two distinct variables called z? I'd recommend avoiding that.