How to return from function lvalue or rvalue based on parameters?

Viewed 90

Consider example:

#include <string>
#include <iostream>

auto get_r_value() { return std::string("hello"); }

int VAL = 15;
int& get_l_value() { return VAL;}

template<typename ...Types> auto&& func(Types... vars) {
    if constexpr (sizeof ... (vars) <= 2) {
        return get_l_value();
    } else {
        return get_r_value();  // warning: returning reference to temporary 
    }
}

int main() {

    auto&& a = get_l_value();
    a = 20;
    std::cout << VAL << std::endl; // print 20
    
    auto&& b = get_r_value();   // auto&& works as expected!
    std::cout << b << std::endl;

    func(1, 2) = 30;  
    std::cout << VAL << std::endl;  // print 30

    std::cout << func(1, 2, 3) << std::endl;  // SEGMENTATION FAULT!
    
    return 0;
}

We can see that the auto&& type not works when it a return type!

Is there any way to return from function lvalue or rvalue based on template parameters?

1 Answers

You might use decltype(auto):

template<typename ...Types> decltype(auto) func(Types... vars) {
    if constexpr (sizeof ... (vars) <= 2) {
        return get_l_value();
    } else {
        return get_r_value();
    }
}

Demo

Related