如何编写一个完美的缩写函数模板?

How to write a perfect Abbreviated Function Template?

本文关键字:完美 缩写 函数模板 一个 何编写      更新时间:2023-10-16

编写缩写函数模板的最佳实践是什么?

我了解,自 C++20 以来,以下是有效代码:

void f(auto&& val) {...}

是否必须使用 decltype(auto( 作为此类函数的返回类型? 特别是,以下代码是编写缩写函数模板的正确方法吗?

decltype(auto) f(auto&& val) {return std::forward<decltype(val)>(val+=2);}
  • 我应该如何专门化上述功能?
//something like this?: 
template<> decltype(auto) f<MyClass>(MyClass& val) {...}

是否必须使用decltype(auto)作为此类函数的返回类型?

取决于您要返回的内容。在这方面,使用缩写模板不会改变任何内容。

特别是,以下代码是编写缩写函数模板的正确方法吗?

正确

使用

decltype(auto) f(auto&& val) {return std::forward<decltype(val)>(val+=2);}
decltype(auto)。但是val在对它执行任何操作之前应该转发:

std::forward<decltype(val)>(val) += 2;

或者,您可以编写:

decltype(val)(val) += 2;

我应该如何专门化上述功能?

//something like this?: 
template<> decltype(auto) f<MyClass>(MyClass& val) {...}

参数的类型为T &&,其中T是隐式模板参数。所以它必须是f<MyClass>(MyClass&& val)f<MyClass &>(MyClass& val).您也可以省略模板参数,让编译器推断它。

但请注意,这种特殊化仅适用于非常量、右值(或左值(MyClass参数。如果你想专门研究参数的所有值类别和 cv-qualifers 的组合,你需要重载它(因为你不能部分专化函数(:

template <typename T>
requires std::same_as<int, std::remove_cvref_t<T>>
decltype(auto) f(T&& val) {return 42;}

或:

decltype(auto) f(auto&& val)
requires std::same_as<int, std::remove_cvref_t<decltype(val)>>
{return 42;}
是否

必须使用decltype(auto)作为此类函数的返回类型?

不。

摘自[dcl.fct]/18/句子-2 [摘录,强调我的]:

缩写函数模板

等效于函数模板 ([temp.fct](,其模板参数列表包括一个发明的类型模板参数,用于函数声明的每个泛型参数类型占位符(按出现顺序(。对于形式auto占位符类型说明符,发明的参数是一个不受约束的类型参数

因此,常规函数模板和缩写函数模板之间没有本质区别,因为使用decltype(auto)作为返回类型;它只是让你能够完美地转发返回类型(就像常规函数模板一样(。


我应该如何专门化上述功能?

根据[dcl.fct]/18[摘录,强调我的]:

[ 示例:

template<typename T>     concept C1 = /* ... */;
template<typename T>     concept C2 = /* ... */;
template<typename... Ts> concept C3 = /* ... */;
void g1(const C1 auto*, C2 auto&);
void g2(C1 auto&...);
void g3(C3 auto...);
void g4(C3 auto);

这些声明在功能上等效(但不等同于(于 以下声明。

template<C1 T, C2 U> void g1(const T*, U&);
template<C1... Ts>   void g2(Ts&...);
template<C3... Ts>   void g3(Ts...);
template<C3 T>       void g4(T);

缩写函数模板可以像所有函数模板一样专用。

template<> void g1<int>(const int*, const double&); // OK, specialization of g1<int, const double>

— 结束示例 ]

你可以专业化,比如说

void f(auto&& val) { (void)val;}

template<>
void f<int>(int&& val) { (void)val;}

演示