gpt4 book ai didi

c++ - 身份别名模板可以作为转发引用吗?

转载 作者:IT老高 更新时间:2023-10-28 22:21:02 25 4
gpt4 key购买 nike

考虑以下片段:

template <class T>
using identity = T;

template <class T>
void foo(identity<T>&&) {}

int main()
{
int i{};
foo(i);
}
i是左值,因此如果 foo声明一个转发引用参数,它应该编译。但是,如果 identity<T>&&变成 int&& ,它应该会引发错误。

代码在 GCC 6.0.0 ( demo ) 中编译。

代码无法在 Clang 3.7.0 ( demo ) 中编译并显示错误消息:
error: no known conversion from 'int' 
to 'identity<int> &&' (aka 'int &&') for 1st argument

哪一个是对的?

最佳答案

考虑这个代码:

template<class T> using identity = T;

template<class T> void foo(identity<T>&&) { } //#1

template<class T> void foo(T&&) { } //#2

int main()
{
int i{};
foo(i);
}

GCC 和 Clang 都拒绝它,因为 #2是对 #1 的重新定义.如果它们实际上是相同的模板,我们可以期待 #1行为方式与 #2 完全相同, 意思是 identity<T>&&应该作为转发引用。按照这个逻辑,我们不知道哪个是对的,但 GCC 至少是一致的。

这也与标准 [14.5.7p2] 中的一个非常相似的示例一致。

我们还应该考虑模板参数推导在这种情况下的工作方式。如 identity是一个类模板,它的形式可以与函数参数的类型匹配而无需查看其定义,从而允许编译器推导出 T 的模板参数。 .但是,这里我们有一个别名模板; T不能推导出 intint&或其他任何东西,除非 identity<T>T 取代.否则,我们匹配什么?替换完成后,函数参数成为转发引用。

以上都支持 identity<T>&&的想法(和 identity<T&&> )被视为等同于转发引用。

然而,似乎还有更多的东西,即用相应的类型 ID 立即替换别名模板 ID。第 [14.5.7p3] 段说:

However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id. [ Example:

template<typename...> using void_t = void; 
template<typename T> void_t<typename T::foo> f();
f<int>(); // error, int does not have a nested type foo

—end example ]



这似乎与您的示例没有太大关系,但它实际上表明在某些情况下仍会考虑模板 ID 的初始形式,而与替换的类型 ID 无关。我想这开启了 identity<T>&& 的可能性。毕竟实际上不能被视为转发引用。

标准中似乎没有详细说明该区域。这表明处理类似问题的未解决问题的数量,在我看来都属于同一类别:在什么情况下,在实例化时应该考虑模板 ID 的初始形式,即使它应该被替换为遇到时立即对应的 type-id。查看问题 1980 , 20212025 .偶问题 14301554可以看作是处理类似的问题。

特别是 issue 1980包含以下示例:
template<typename T, typename U> using X = T;
template<typename T> X<void, typename T::type> f();
template<typename T> X<void, typename T::other> f();

附注:

CWG felt that these two declarations should not be equivalent.



(CWG - 核心工作组)

类似的推理也适用于您的示例,即 identity<T>&&不等同于转发引用。这甚至可能具有实用值(value),作为一种直接的方法,当您只需要对推导的 T 的右值引用时,可以避免转发引用的贪婪。

所以,我认为你提出了一个非常有趣的问题。您的示例可能值得作为注释添加到 issue 1980 ,以确保在起草决议时考虑到这一点。

在我看来,你的问题的答案目前是一个响亮的“谁知道?”。

更新:在对其他相关的评论中, question , Piotr S.指出 issue 1700 ,它被关闭为“不是缺陷”。它指的是该问题中描述的非常相似的案例,并包含以下基本原理:

Because the types of the function parameters are the same, regardless of whether written directly or via an alias template, deduction must be handled the same way in both cases.



我认为它也适用于这里讨论的案例,并暂时解决了这个问题:所有这些表格都应该被视为等同于转发引用。

(看看其他未决问题的决议是否间接改变了这一点会很有趣,但它们主要处理替代失败而不是其本身的推论,所以我猜这种间接影响是不太可能的。)

所有标准引用均针对当前工作草案 N4431,即最终 C++14 之后的第二个草案。

请注意,[14.5.7p3] 中的引用是最近添加的,在最终的 C++14 版本之后作为 DR1558 的分辨率包含在内。 .我认为随着其他问题以某种方式得到解决,我们可以期待在这方面有更多的补充。

在此之前,可能值得在 ISO C++ Standard - Discussion 中提出这个问题。团体;这应该引起合适的人的注意。

关于c++ - 身份别名模板可以作为转发引用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29851098/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com