扣除在类模板中声明的朋友函数的模板参数
考虑以下示例:
#include <iostream>
template <class T, int V>
struct S
{
friend int Func(T) // decl-1
{
return V;
}
};
struct U
{
friend int Func(U); // decl-2
};
template struct S<U, 42>; // spec-1
int main()
{
std::cout << Func(U{}) << std::endl; // Compiles and prints 42
}
我的理解是func(u {})
导致函数func
的不合格的名称查找,并且通过ADL查找声明 ext -2 。 但是,这不是过载分辨率的可行候选功能(由于未定义),因此编译器选择声明 exl> ext-1 。。 误解和与问题无关,请参阅@languagelawyer的评论
我的问题是标准中的哪个规则允许编译器使用“专业化”模板参数 类模板。
spec-1 实例化包含 dect-1 的 /cpp“ rel =“ nofollow noreferrer”> cppReference ,我发现似乎应用的唯一规则是指函数模板的过载分辨率,并引用:
对于函数模板,执行模板参数扣除和检查任何明确的模板参数以查找在这种情况下可以使用的模板参数值(如果有):
- 如果两者都成功,则使用模板参数来综合相应函数模板专业的声明,这些声明被添加到候选集合中,并且该专业的处理方式就像非网板函数一样处理规则;
- 如果参数扣除失败或合成函数模板专业化将是不形式的,则不会将此类功能添加到候选人集中。
来源: https://en.cppreference.com/w/cpp /语言/Overload_resolution#详细信息
IS ext-1 考虑了一个函数模板,以实现超载的目的 解决?编译器是否合成声明模板int func&lt; u,42&gt;(u)
使用 spec-1 (通过模板参数扣除,大概是)?还是这里有其他事情在这里?
编辑:我可能拥有的另一种误解是 spec-1 ,我目前的理解是,这是对类模板的明确专业化的声明S
作为不完整的类型,如果可能的话,请澄清一下。
Consider the following example:
#include <iostream>
template <class T, int V>
struct S
{
friend int Func(T) // decl-1
{
return V;
}
};
struct U
{
friend int Func(U); // decl-2
};
template struct S<U, 42>; // spec-1
int main()
{
std::cout << Func(U{}) << std::endl; // Compiles and prints 42
}
My understanding is that the expression Func(U{})
causes an unqualified name lookup of the function Func
, and through ADL finds declaration decl-2. However, this is not a viable candidate function for overload resolution (since it is not defined), and thus the compiler selects declaration decl-1. Misunderstanding, and irrelevant to the question, see comment from @LanguageLawyer
My question is what rule(s) in the standard allow the compiler to use the template parameters from the specialization spec-1 to instantiate the class template that contains decl-1.
Searching through cppreference, the only rule I found that seems to apply refers to overload resolution of function templates, and to cite:
For function templates, template argument deduction and checking of any explicit template arguments are performed to find the template argument values (if any) that can be used in this case:
- if both succeeds, the template arguments are used to synthesize declarations of the corresponding function template specializations, which are added to the candidate set, and such specializations are treated just like non-template functions except where specified otherwise in the tie-breaker rules;
- if argument deduction fails or the synthesized function template specialization would be ill-formed, no such function is added to the candidate set.
Source: https://en.cppreference.com/w/cpp/language/overload_resolution#Details
Is decl-1 considered a function template for the purposes of overload resolution? Does the compiler synthesize a declaration template int Func<U, 42>(U)
using spec-1 (through template argument deduction, presumably)? Or is something else at play here?
EDIT: An additional misconception that I may have is what exactly is spec-1, my current understanding is that it is the declaration of an explicit specialization of class template S
as an incomplete type, if possible please clarify if this is correct.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是在哪个指出:
(强调我的)
并且由于
spec-1
是 显式实例定义,结果将是类模板专业化的实例化s&lt; u,42&gt; < /代码>
否,
ext-1
是普通(非网板)函数的定义。 Moroever,此ext-1
不过是在exling-2
中声明的函数的定义。This is specified in temp.explicit-12 which states that:
(emphasis mine)
And since
spec-1
is an explicit instantiation definition, the result will be the instantiation of the class template specializationS<U, 42>
No,
decl-1
is a definition for an ordinary(non-template) function. Moroever, thisdecl-1
is nothing but the definition for the function declared indecl-2
.这是不正确的。
根本不是专业,而是。
它只是告诉编译器使用参数发射
s
的相同实例化t = u
和v = 42
,如果您引用了,则会发出。在任何其他情况下,s&lt; u,24&gt;
。作为不完整类型的专业化看起来像
This is not correct.
Is not a specialization at all, but an explicit instantiation.
It just tells the compiler to emit the same instantiation of
S
with parametersT=U
andV=42
that would have been emitted if you referred toS<U, 24>
in any other context.A specialization as an incomplete type looks like