加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 当函数参数是const引用T时,为什么T’的模板参数推导会跳过

发布时间:2020-12-16 07:12:38 所属栏目:百科 来源:网络整理
导读:让我们考虑一下这些定义: /*** full type information with typeid ***/template class class Type{};template class T std::string typeStr(){ return typeid(TypeT).name(); }/*** function template for parameter deduction ***/template class T void
让我们考虑一下这些定义:

/*** full type information with typeid ***/
template <class> class Type{};

template <class T> std::string typeStr()
{ return typeid(Type<T>).name(); }

/*** function template for parameter deduction ***/
template <class T> void func(const T &a)
{
    std::cout << "Deduced type for T is: " << typeStr<T>() << std::endl;
    std::cout << "targument type is: " << typeStr<decltype(a)>() << std::endl;
}

用指针指向const

如果执行以下语句:

const int i=5,*ip=&i;
func(ip);

输出是:

Deduced type for T is: 4TypeI**PKi**E

因此,T实际上被推导为指向常数整数的指针.参数是const的引用这一事实不会改变推论,这是人们所期望的,因为指针的常量是低级的.

但是使用const数组

但是,如果执行以下语句:

const int ia[3] = {3,2,1};
func(ia);

输出是:

Deduced type for T is: 4TypeI**A3_i**E

因此,T实际上被推导为3个非常数整数的数组.参数是const的引用这一事实确实改变了推论,就好像const正在滑入数组元素一样.

实际上,最多18个CL的版本推导T为3个const整数的数组是我期望的标准,但似乎从v19它收敛到GCC和Clang正在做的事情(即推导为非const).

因此,我认为后来的行为是标准的,但是理由是什么?它看起来不像指针一样令人惊讶.

编辑:在评论之后,我将在这里报告与此行为相关的CWG问题的指针,他实际发布的指针作为对this answer的评论(回答实际上提出了这个新问题…… C感觉就像一个深隧道)

> CWG 1059
> CWG 1610
> CWG 112

解决方法

使用此函数模板原型:

template <typename T> void func(const T& a);

在第一个示例中,类型推导的工作原理如下:

const int* ip;

func(ip) => func<const int*>(const (const int*)& a)
                 ^^^^^^^^^^         ^^^^^^^^^^

注意:这是伪代码.完整类型是const int * const&.

请注意,const int仍然是const int,但*变为* const.

这是因为const int *只是一个常规的,可变的,非易失性的指针.这只是一个*.它所指的是无关紧要的.

但在第二个例子中,你有:

const int ia[3];

func(ia) => func<int[3]>(const (int[3])& a)
                 ^^^^^^         ^^^^^^

注意:这是伪代码.真实的类型是const int(& a)[3].

因此类型推导在两种情况下都是相同的,丢弃外部const.

碰巧const数组与const元素数组相同.

写这样的类型可能会有所帮助:

template <typename T> func(T const & a);

int const * ip;

func(ip) => func<int const *>(int const * const & a)

int const ia [3];

func(ia) => func<int [3]>(int const (& a) [3])

在第二个例子中,const似乎“移动”从应用于数组到应用于元素.这是因为你不能真正拥有const数组,只有const数组的数组.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读