C++-转换函数模板推导,为什么会这样?
C++-conversion function template deduction, why does this work?
class A
{
struct B{};
public:
static void test(A::B){}
};
struct C
{
template<class T>
operator T()
{
return T();
}
};
int main()
{
A::test(C());
}
此代码适用于 clang 3.7、gcc 5.1 和 vc++ 14.2。
2 个问题,
1、为什么template可以推导出type是A::B? (太聪明了!)
据我所知,模板通过 return 语句而不是参数推导类型。
但是我发现了一些对 N4606 12.3.2 6 感兴趣的东西A conversion function template shall not have a deduced return type (7.1.7.4).
(但是我找不到关于这个的更多信息,因为 7.1.7.4 太难理解了。)
2、为什么转换函数模板可以访问A::B?
谢谢。
- Why can template deduce the type is A::B? (so smart!)
由于 test()
采用 A::B
,您需要一种方法将 C
转换为 A::B
。我们可以尝试通过转换函数进行初始化,为此我们在 [over.match.conv]:
The conversion functions of S
and its base classes are considered. Those non-explicit conversion
functions that are not hidden within S
and yield type T
or a type that can be converted to type T
via
a standard conversion sequence (13.3.3.1.1) are candidate functions.
我们根据[temp.conv]进行模板推导:
Template argument deduction is done by comparing the return type of the conversion function template (call
it P) with the type that is required as the result of the conversion (call it A; see 8.6, 13.3.1.5, and 13.3.1.6 for
the determination of that type) as described in 14.8.2.5.
基本上,我们推导出template <class T> operator T()
中的T
为A::B
。这是一个格式正确的转换序列,也是唯一可行的,所以就是这样。
你引用的那行,关于"deduced return type",指的是return类型中的auto
或decltype
。这不会发生在这里。
- Why could conversion function template access A::B?
访问规则严格与名称有关。 name B
,只有名字,是 A
私有的。但是我们没有访问 name,我们直接推导类型。
B
的构造函数是public,所以转换函数的主体也是良构的,所以代码的一切都是良构的。
稍微简化一下:
将内部 class 或函数设为私有仅意味着 class 或函数的名称只能由 class 使用,否则无法访问。您不能在 class.
之外编写任何使用名称 private class 或函数的代码
在显示的代码中 A::B
未在 class 之外的任何地方使用。
这也有效,原因完全相同:
class A {
class B {};
public:
B foo();
};
int main()
{
A a;
auto bar=a.foo();
return 0;
}
auto
有效。 A::B
将不起作用。
class A
{
struct B{};
public:
static void test(A::B){}
};
struct C
{
template<class T>
operator T()
{
return T();
}
};
int main()
{
A::test(C());
}
此代码适用于 clang 3.7、gcc 5.1 和 vc++ 14.2。
2 个问题,
1、为什么template可以推导出type是A::B? (太聪明了!)
据我所知,模板通过 return 语句而不是参数推导类型。
但是我发现了一些对 N4606 12.3.2 6 感兴趣的东西A conversion function template shall not have a deduced return type (7.1.7.4).
(但是我找不到关于这个的更多信息,因为 7.1.7.4 太难理解了。)
2、为什么转换函数模板可以访问A::B?
谢谢。
- Why can template deduce the type is A::B? (so smart!)
由于 test()
采用 A::B
,您需要一种方法将 C
转换为 A::B
。我们可以尝试通过转换函数进行初始化,为此我们在 [over.match.conv]:
The conversion functions of
S
and its base classes are considered. Those non-explicit conversion functions that are not hidden withinS
and yield typeT
or a type that can be converted to typeT
via a standard conversion sequence (13.3.3.1.1) are candidate functions.
我们根据[temp.conv]进行模板推导:
Template argument deduction is done by comparing the return type of the conversion function template (call it P) with the type that is required as the result of the conversion (call it A; see 8.6, 13.3.1.5, and 13.3.1.6 for the determination of that type) as described in 14.8.2.5.
基本上,我们推导出template <class T> operator T()
中的T
为A::B
。这是一个格式正确的转换序列,也是唯一可行的,所以就是这样。
你引用的那行,关于"deduced return type",指的是return类型中的auto
或decltype
。这不会发生在这里。
- Why could conversion function template access A::B?
访问规则严格与名称有关。 name B
,只有名字,是 A
私有的。但是我们没有访问 name,我们直接推导类型。
B
的构造函数是public,所以转换函数的主体也是良构的,所以代码的一切都是良构的。
稍微简化一下:
将内部 class 或函数设为私有仅意味着 class 或函数的名称只能由 class 使用,否则无法访问。您不能在 class.
之外编写任何使用名称 private class 或函数的代码在显示的代码中 A::B
未在 class 之外的任何地方使用。
这也有效,原因完全相同:
class A {
class B {};
public:
B foo();
};
int main()
{
A a;
auto bar=a.foo();
return 0;
}
auto
有效。 A::B
将不起作用。