[300分]关于从T&到T的模板实参推演有关问题的讨论
[300分]关于从T&到T的模板实参推演问题的讨论
问题来自于新的auto关键字不能取得"引用"的类型啊,为什么? 这个帖子,主题意思是从T&到T的实参推演结果是T的原因是什么,包括偶在内有多人提出了自己的看法,虽然楼主也给了分,但实际上没有一个帖子道出了真正的原因。老实说偶一直没有注意到这个问题,通常的模板基础书籍例如C++ template等也没谈到,偶在C++11中翻了半天也没找到具体的条款,在C++98/03中测试了一下,发现从98/03起就是这样推导的了,并不是11的专利,为了问题描述方便,偶提供了98/03下的代码:
大家可以看到,虽然实参是int&,但从fun中推导出的T是int,不是int&,但如果是int*,则推导出来的就是int*,请大家都谈一下自己的看法,谢谢!
------解决方案--------------------
------解决方案--------------------
实参真的是引用类型吗?
定义引用类型的变量只是指明了一个别名,使用引用的变量的时候应该和直接使用它引用的东西本质上是一样的,已经没有是否是引用的区别了。
------解决方案--------------------
fun( a ); 只是使用了a引用的那个值而已,模板推导的结果就是int了。
------解决方案--------------------
指针不是引用,而是一种实类型,和int一样。
auto的结果相当于
中,当使用自动匹配形式的func调用时的val的类型(即调用时不显式的填入模版参数)。
函数传值型模板自动推导或者auto推导过程中将会放弃前缀属性(cv-qualifies);而模板特化的匹配,这些属性都是完整保留下来的。
------解决方案--------------------
以下代码不完全,随手打得未验证。只是说明原理:
然后RemoveCV<const volatile int &>::type其实就是int,引用、cv属性等都会丢失。
问题来自于新的auto关键字不能取得"引用"的类型啊,为什么? 这个帖子,主题意思是从T&到T的实参推演结果是T的原因是什么,包括偶在内有多人提出了自己的看法,虽然楼主也给了分,但实际上没有一个帖子道出了真正的原因。老实说偶一直没有注意到这个问题,通常的模板基础书籍例如C++ template等也没谈到,偶在C++11中翻了半天也没找到具体的条款,在C++98/03中测试了一下,发现从98/03起就是这样推导的了,并不是11的专利,为了问题描述方便,偶提供了98/03下的代码:
template< typename T >
struct is_reference
{
enum { value = 0 };
}
template< typename T >
struct is_reference< T& >
{
enum { value = 1 };
}
template< typename T >
void fun( T t )
{
std::cout << is_reference< T >::value;
}
int main( void )
{
int i, &a = i;
fun( a );
return 0;
}
大家可以看到,虽然实参是int&,但从fun中推导出的T是int,不是int&,但如果是int*,则推导出来的就是int*,请大家都谈一下自己的看法,谢谢!
------解决方案--------------------
#include <iostream>
template< typename T >
struct is_reference {
enum { value = 0 };
};
template< typename T >
struct is_reference< T& > {
enum { value = 1 };
};
int main(int argc, char* argv[]) {
int i, &a = i;
std::cout << is_reference< decltype(a) >::value << std::endl;
}
------解决方案--------------------
实参真的是引用类型吗?
定义引用类型的变量只是指明了一个别名,使用引用的变量的时候应该和直接使用它引用的东西本质上是一样的,已经没有是否是引用的区别了。
------解决方案--------------------
fun( a ); 只是使用了a引用的那个值而已,模板推导的结果就是int了。
------解决方案--------------------
指针不是引用,而是一种实类型,和int一样。
auto的结果相当于
template < typename Ty >
void func(Ty val);
中,当使用自动匹配形式的func调用时的val的类型(即调用时不显式的填入模版参数)。
函数传值型模板自动推导或者auto推导过程中将会放弃前缀属性(cv-qualifies);而模板特化的匹配,这些属性都是完整保留下来的。
------解决方案--------------------
以下代码不完全,随手打得未验证。只是说明原理:
template < typename _Ty >
struct RemoveCV
{
_Ty GenerateVal(void);
template < typename _auto_t > _auto_t fGetType(_auto_t);
typedef decltype(fGetType(GenerateVal())) type;
};
然后RemoveCV<const volatile int &>::type其实就是int,引用、cv属性等都会丢失。