提问人:cppBeginner 提问时间:8/10/2023 最后编辑:cppBeginner 更新时间:8/16/2023 访问量:137
可以接收任何 T、T& 和 T&& 作为输入的函数,并且还可以识别其类型?
Function that can receive any of T, T&, and T&& as input, AND also recognize its type?
问:
我想创建一个正确识别其参数类型的函数。
template<class T> void test(T&& t){
if constexpr(std::is_same_v<T,int>){
std::cout<< "= int"<<std::endl;
}
if constexpr(std::is_same_v<T,const int&>){
std::cout<< "= const int&"<<std::endl;
}
if constexpr(std::is_same_v<T,int&>){
std::cout<< "= int&"<<std::endl;
}
if constexpr(std::is_same_v<T,int&&>){
std::cout<< "= int&&"<<std::endl;
}
if constexpr(std::is_same_v<T,std::nullptr_t>){
std::cout<< "= std::nullptr_t"<<std::endl;
}
}
int funcReturnInt(){return 5;}
int main(){
const int a=0;
test(funcReturnInt()); // int (correct)
test(a); // const int& (correct)
test(nullptr); // std::nullptr_t (correct)
int s=0;
test(std::move(s)); // print "int" (not "int&&") , I am sad
}
如何创建函数,以便它可以在每种情况下正确识别其单个参数的类型?test()
我是新手,所以我阅读了一些关于右值引用(1、2、3)的指南,但它们没有描述如何创建这样一个完全感知的通配符函数,例如 。T&&
test<T>(T??)
我稍后将应用该解决方案。test() requires ... {}
我宁愿避免重载,因为我喜欢将代码压缩在 1 个地方(也用于教育目的)。
编辑 :: 非常有用的评论指出这通常是不可能的。为什么我的代码正确检查其他情况,但 C++ 会冒昧地摆脱我的?请将其作为解决方案发布。&&
我仍然怀疑为什么 in 变得正确,但在 成为.int&
main()
T=int&
int&&
main()
T=int
答:
强调我的:
我是新手,所以我阅读了一些关于右值引用(1、2、3)的指南,但它们没有描述如何创建这样一个完全感知的通配符函数,例如 。
T&&
test<T>(T??)
在此声明中:
template<class T> void test(T&& t)
虽然经常被误认为是右值引用,但它不是右值引用,而是转发引用(有时称为通用引用)。要理解转发引用,我们需要了解的不仅仅是右值引用,例如引用折叠规则和完美转发。有关详细信息,请参阅以下问答:t
我仍然怀疑为什么在 main() 中变得正确,但在 中变成了 'T=int。
int&
T=int&
int&&
main()
在通话中
test(std::move(s));
参数类型 A 是 ,完整的参数类型是 表示推导的 是int&&
int&&
T
int
test<int>(int&& t);
^^^ ^^^^^ parameter-type (T&& -> int&&)
\ deduced T
有关详细信息,请参阅例如 [temp.deduct.call]/3。
当参数类型为左值时,通用引用尤其应用引用折叠规则。对于调用,参数类型是 ,但出于演绎的目的,用于就地,推导到 ,其中生成的函数参数类型从 折叠到 ( -> )。test(a)
int const
int const&
T
int const&
T&&
int const& &&
int const&
&& &
&
评论
test(std::move(s))
导致 rvalue 引用到右值引用”。你确定这是正确的吗?IIRC,这里将模板参数推导出为 only,然后替换为 。因此,该参数是直接的右值引用,不应用任何折叠规则。现场演示:godbolt.org/z/M3W8baKan。int
T
t
T
int
int&&
T
T&&
T
int
int&
评论
T &&
T
decltype
test(42);
test(std::move(s))
int &&