Search code examples
c++c++17stdvectorautostdtuple

The compiler bug? Returning std::vector and std::string in std::tuple. But I got strange values


I would like to return multiple values and declare that function using auto.

But that does not work well. Values can not be returned correctly. It was overwritten.

I try to execute following functions f1~f3. Those function should return vector and string in tuple. But only f3 works well.

#include <iostream>
#include <vector>
#include <string>
#include <tuple>

auto f1(){
    std::vector<double> v(10, 0);
    std::string s = "hello";
    return std::forward_as_tuple(v, s);
}

auto f2(){
    std::vector<double> v(10, 0);
    return std::forward_as_tuple(v, "hello");
}

std::tuple<std::vector<double>, std::string> f3(){
    std::vector<double> v(10, 0);
    std::string s = "hello";
    return std::forward_as_tuple(v, s);   
}
int main(void){
    //change the function
    //auto [vec, str] = f1();
    //auto [vec, str] = f2();
    auto [vec, str] = f2();

    for (auto e : vec){
        std::cout << "vec : " << e << std::endl;
    }

    std::cout << "str : " << str << std::endl;
}

You can also execute this program at online compiler wandbox from this link.

  • f1() causes an segmentation fault.
  • f2() returns wrong values in std::vector. It seems random number.
  • f3() returns all values correctly.

Why does this problem occur? Is it impossible to return multiple values and declare that function using auto?


Solution

  • The problem occurs because std::forward_as_tuple returns references to local variables - the return type is tuple<vector<double>&,string&>.

    The first two functions produce undefined behaviour.

    The third one works because you explicitly return by value, although the forwarding doesn't work because you did not move the l-values so they get copied into the returned tuple.

    The correct way to return a tuple is just:

    return std::tuple{std::move(vec),std::move(str)};