如何写出完美的缩略函数模板?
How to write a perfect Abbreviated Function Template?
编写缩写函数模板的最佳做法是什么?
我明白,自 C++20 起,以下是有效代码:
void f(auto&& val) {...}
是否必须使用 decltype(auto) 作为此类函数的 return 类型?
特别是,下面的代码是编写缩写函数模板的正确方法吗?
decltype(auto) f(auto&& val) {return std::forward<decltype(val)>(val+=2);}
- 我应该如何专门化上述功能?
//something like this?:
template<> decltype(auto) f<MyClass>(MyClass& val) {...}
Is it essential to use decltype(auto)
as the return type of such functions?
取决于您返回的内容。使用缩写模板在这方面没有任何改变。
In particular, is the following code the right way to write abbreviated function templates?
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;
How should I specialize the above function?
//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;}
Is it essential to use decltype(auto)
as the return type of such functions?
没有
来自[dcl.fct]/18/sentence-2[摘录,强调我的]:
An abbreviated function template is equivalent to a function template ([temp.fct]) whose template-parameter-list includes one invented type template-parameter for each generic parameter type placeholder of the function declaration, in order of appearance. For a placeholder-type-specifier of the form auto
, the invented parameter is an unconstrained type-parameter.
因此,正则函数模板和缩略函数模板之间没有本质区别w.r.t。 decltype(auto)
作为 return 类型的用法;它只是让您能够完美转发 return 类型(与常规函数模板一样)。
How should I specialize the above function?
根据 [dcl.fct]/18 [摘录,强调 我的]:
[...] [ Example:
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);
These declarations are functionally equivalent (but not equivalent) to
the following declarations.
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);
Abbreviated function templates can be specialized like all function templates.
template<> void g1<int>(const int*, const double&); // OK, specialization of g1<int, const double>
— end example ]
你可以专攻,比如说
void f(auto&& val) { (void)val;}
为
template<>
void f<int>(int&& val) { (void)val;}
DEMO.
编写缩写函数模板的最佳做法是什么?
我明白,自 C++20 起,以下是有效代码:
void f(auto&& val) {...}
是否必须使用 decltype(auto) 作为此类函数的 return 类型? 特别是,下面的代码是编写缩写函数模板的正确方法吗?
decltype(auto) f(auto&& val) {return std::forward<decltype(val)>(val+=2);}
- 我应该如何专门化上述功能?
//something like this?:
template<> decltype(auto) f<MyClass>(MyClass& val) {...}
Is it essential to use
decltype(auto)
as the return type of such functions?
取决于您返回的内容。使用缩写模板在这方面没有任何改变。
In particular, is the following code the right way to write abbreviated function templates?
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;
How should I specialize the above function?
//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;}
Is it essential to use
decltype(auto)
as the return type of such functions?
没有
来自[dcl.fct]/18/sentence-2[摘录,强调我的]:
An abbreviated function template is equivalent to a function template ([temp.fct]) whose template-parameter-list includes one invented type template-parameter for each generic parameter type placeholder of the function declaration, in order of appearance. For a placeholder-type-specifier of the form
auto
, the invented parameter is an unconstrained type-parameter.
因此,正则函数模板和缩略函数模板之间没有本质区别w.r.t。 decltype(auto)
作为 return 类型的用法;它只是让您能够完美转发 return 类型(与常规函数模板一样)。
How should I specialize the above function?
根据 [dcl.fct]/18 [摘录,强调 我的]:
[...] [ Example:
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);
These declarations are functionally equivalent (but not equivalent) to the following declarations.
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);
Abbreviated function templates can be specialized like all function templates.
template<> void g1<int>(const int*, const double&); // OK, specialization of g1<int, const double>
— end example ]
你可以专攻,比如说
void f(auto&& val) { (void)val;}
为
template<>
void f<int>(int&& val) { (void)val;}
DEMO.