【发布时间】:2019-06-29 00:35:41
【问题描述】:
考虑以下情况,在模板参数中添加const 有什么效果?
案例 1:void func() 通过复制获取 T 类型的参数
#include <iostream>
#include <boost/type_index.hpp>
template<typename T>
void func(T val_)
{
using boost::typeindex::type_id_with_cvr;
std::cout<< "type of `val_` is `" << type_id_with_cvr< decltype(val_) >().pretty_name() << "`" <<std::endl;
}
int main()
{
int *f = new int(2);
func<int>(2); // type of `val_` is `int` - OK
func<int*>( f ); // type of `val_` is `int*` - OK
func<const int*>( f ); // type of `val_` is `int const*` - OK
func<const int* const>( f ); // type of `val_` is `int const* const` - OK
}
第一个案例没有问题...很清楚发生了什么。
案例2:void func() 通过引用获取T 类型的参数
#include <iostream>
#include <boost/type_index.hpp>
template<typename T>
void func(T &val_)
{
using boost::typeindex::type_id_with_cvr;
std::cout<< "type of `val_` is `" << type_id_with_cvr< decltype(val_) >().pretty_name() << "`" <<std::endl;
}
int main()
{
int *f = new int(2);
func<int>(2); // error - OK
func<int*>( f ); // type of `val_` is `int*&` - OK
func<const int*>( f ); // error: no known conversion from 'int *' to 'const int *&' - OK
func<const int* const>( f ); // type of `val_` is `int const* const&` - ???
}
案例 3:void func() 通过转发/通用引用获取 T 类型的参数
#include <iostream>
#include <boost/type_index.hpp>
template<typename T>
void func(T &&val_)
{
using boost::typeindex::type_id_with_cvr;
std::cout<< "type of `val_` is `" << type_id_with_cvr< decltype(val_) >().pretty_name() << "`" <<std::endl;
}
int main()
{
int *f = new int(2);
func<int>(2); // type of `val_` is `int&&` - OK
func<int*>( f ); // error: no known conversion from 'int *' to 'int *&&' - OK
func<const int*>( f ); // type of `val_` is `int const*&&` - ???
func<const int* const>( f ); // type of `val_` is `int const* const&&` - ???
}
问题 #1: 在案例 #2 中,为什么 func<const int* const>( f ); 仅通过添加 rhs const 就被接受了?
问题 #2: 在案例 #3 中,为什么仅通过添加 const 就可以接受对 func 的最后两次调用?
问题 #3: 在案例 #3 中,使用转发引用的好处是,如果函数参数是左值,那么 val_ 的类型将是左值引用。如果参数是一个右值,那么val_ 的类型将是一个右值。因此,传递左值f 应该使T 成为int*&。当您没有在函数调用时指定模板参数int* 时,情况确实如此。但是,当您指定模板参数int* 时,结果是int*&&。为什么?
【问题讨论】:
-
我们假设推断转发/通用引用的参数。
-
对于案例 1,您可以使用
func<int*&>/func<int*&&>处理 case2/case3。