3

I have a function that has the return type set to auto. If I want to return something by reference, normally I can simply hint the compiler with -> T&. However in my specific case I have a templated function which has different return paths defined through an if constexpr expression. Something like this:

template<typename T>
auto fn(T& arg)
{
    if constexpr (std::is_same_v<T, int>)
        return;
    else
        return arg;
}

I want to return arg by reference in the second case. Is there a way to hint the compiler as to the type inside the function body? I know that I can do std::ref(arg), but then the returned type is a reference wrapper, so if I do auto& res = fn(arg) it simply fails when I try to use it as an actual reference. Basically I want the vanilla behaviour one would get through -> T&, but for a function that can return various types, so I want to provide the hint within the function body.

lightxbulb
  • 1,251
  • 12
  • 29

2 Answers2

3

Use decltype(auto) instead, which evaluates to the exact type of the expression you're returning:

template<typename T>
decltype(auto) fn(T& arg)
{
    if constexpr (std::is_same_v<T, int>)
        return;
    else
        return arg;
}
  • When calling int i; fn(i);, the return type will be void.

  • When calling float f; fn(f);, the return type will be float&.

live example on godbolt.org with static_assert evidence

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
1

That's what decltype(auto) is for. Just change your signature to

template<typename T>
decltype(auto) fn(T& arg)
SergeyA
  • 61,605
  • 5
  • 78
  • 137