Bat*_*eba 43 c++ templates function-templates template-argument-deduction argument-deduction
考虑
#include <iostream>
#include <type_traits>
template <class T, class ARG_T = T&>
T foo(ARG_T v){
return std::is_reference<decltype(v)>::value;
}
int main() {
int a = 1;
std::cout << foo<int>(a) << '\n';
std::cout << foo<int, int&>(a) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我希望两种情况下的输出均为1。但在第一种情况下为0:与默认值class ARG_T = T
而不是一致class ARG_T = T&
。
我想念什么?
Sto*_*ica 43
对于foo<int>(a)
,ARG_T
是从推导出的a
,而不是从默认模板参数中提取的。由于它是一个按值函数参数,并且a
是类型的表达式int
,因此推导为int
。
通常,当模板参数推导可以发现参数是什么时,不使用默认模板参数。
但是我们可以通过为函数参数引入非推导上下文来强制使用默认参数。例如:
template <class T, class ARG_T = T&>
T foo(std::enable_if_t<true, ARG_T> v1){
//...
}
Run Code Online (Sandbox Code Playgroud)
或C ++ 20 type_identity
实用程序,如其他答案所示。
son*_*yao 29
你需要停下模板参数推导为ARG_T
从功能参数v
,(的帮助下std::type_identity
,它可以用来排除特定扣除参数); 否则,将不使用默认模板参数。例如
template <class T, class ARG_T = T&>
T foo(std::type_identity_t<ARG_T> v){
return std::is_reference<decltype(v)>::value;
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句:如果您的编译器不支持std::type_identity
(从C ++ 20开始),您可以自己制作。
template<typename T> struct type_identity { typedef T type; };
template< class T >
using type_identity_t = typename type_identity<T>::type;
Run Code Online (Sandbox Code Playgroud)