简体   繁体   中英

How can I write a function template that returns either a reference or a value?

I'd like to write a function template that returns either a reference or a value depending on some compile time expression. What I've tried so far is something like this:

template<typename T>
auto&& Func()
{
  if constexpr (some_compile_time_expression)
  {
    return GetReferenceFromSomewhere();
  }
  else
  {
    return GetValueFromSomewhere();
  }
}

This works fine for all types of references but doesn't work for values. For example, if GetValueFromSomewhere returns a Foo , then the compiler deduces the return type of Func as Foo&& and warns that I'm returning the address of a temporary.

Is there any way to make this work, or am I forced to tease the two branches apart somehow (through function overloads or some such)?

Use decltype(auto) for the return type placeholder, it will preserve the exact value category of the function you're calling in the return statement

template<typename T>
decltype(auto) Func()
{
  if constexpr (some_compile_time_expression_dependent_on_T)
  {
    return GetReferenceFromSomewhere();
  }
  else
  {
    return GetValueFromSomewhere();
  }
}

Live demo

Pretorian's answer is perfect, but you may also want to learn about std::conditional , which has broader usage. For example, consider a data_ member variable of type int and a member function, that returns data_ either by reference or by value depending on some compile-time condition:

template <bool COND>
std::conditional_t<COND, int&, int> data() { return data_; }

This would not be achievable with decltype(auto) . You can also use the same technique to pass arguments to functions by reference/value:

template <bool COND>
void f(std::conditional_t<COND, int&, int> param);

Or, you can switch between copy/move constructors:

class X {
    X(std::conditional_t<some_cond, const X&, X&&>) = default;
    X(std::conditional_t<some_cond, X&&, const X&>) = delete;
    ...
};

Etc...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM