如何编写返回引用或值的函数模​​板?

Pet*_*man 11 c++ templates c++17

我想编写一个函数模板,它根据一些编译时表达式返回一个引用或一个值.到目前为止我尝试的是这样的:

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

这适用于所有类型的引用,但不适用于值.例如,如果GetValueFromSomewhere返回a Foo,那么编译器会推断Funcas 的返回类型,Foo&&并警告我正在返回临时的地址.

有没有办法让这个工作,或者我被迫以某种方式分开两个分支(通过功能重载或一些这样的)?

Pra*_*ian 16

使用decltype(auto)返回类型占位符,它会保留你在调用该函数的精确值类return声明

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

现场演示


Dan*_*ica 5

Pretorian 的答案很完美,但您可能还想了解std::conditional,它有更广泛的用途。例如,考虑一个data_类型的成员变量int和一个成员函数,它data_根据某些编译时条件通过引用或值返回:

template <bool COND>
std::conditional_t<COND, int&, int> data() { return data_; }
Run Code Online (Sandbox Code Playgroud)

这是无法实现的decltype(auto)。您还可以使用相同的技术通过引用/值将参数传递给函数:

template <bool COND>
void f(std::conditional_t<COND, int&, int> param);
Run Code Online (Sandbox Code Playgroud)

或者,您可以在复制/移动构造函数之间切换:

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

ETC...

  • 我确实尝试过使用“std::conditional”。这并不漂亮。 (2认同)