扣除模板时,合格和不合格的名称查找有什么区别?
What is the difference between qualified and unqualified name lookup when deducting templates?
在编写模板方法时,我 运行 出现了以下行为,我不明白。
我有以下代码:
#include <array>
#include <iostream>
namespace A
{
template<typename T>
class Bar
{
T Var;
};
}
namespace B
{
template<typename T>
void Foo(const T& var)
{
std::cout << "default template method has been called" << std::endl << std::endl;
}
template<typename T, size_t N>
void Foo(const std::array<T,N>& var)
{
std::cout << "Array overload has been called" << std::endl;
for(auto& elem : var)
{
Foo(elem);
}
}
template<typename T>
void Foo(const A::Bar<T>& var)
{
std::cout << "Bar overload has been called" << std::endl << std::endl;
}
}
int main()
{
int VarInt;
A::Bar<int> VarBar;
std::array<int, 1> ArrayInt;
std::array<A::Bar<int>, 1> ArrayBar;
B::Foo(VarInt);
B::Foo(VarBar);
B::Foo(ArrayInt);
B::Foo(ArrayBar);
return 0;
}
它的输出不是我对 Bar 数组的预期,调用默认模板而不是 Bar 重载:
default template method has been called
Bar overload has been called
Array overload has been called
default template method has been called
Array overload has been called
default template method has been called
我注意到执行以下操作可以使编译器找到正确的重载:
- 删除所有名称空间或
- 在实现之前声明所有模板原型
It's output is not what i expect as with the array of Bar, the default template is called instead of the Bar overload
对于调用表达式 B::Foo(ArrayBar)
,选择第二个重载 void Foo(const std::array<T,N>& var)
,其中 N
推导为 1
,T
推导为 A::Bar<int>
.
现在在该重载中,当遇到调用表达式 Foo(elem)
时,编译器不知道第三个重载 Foo
。因此它选择 Foo
的第一个重载,这是当时可用的两个重载中最通用的。
declaring all the templates prototypes before implementing them
在实现 Foo
的所有重载之前提供它们的声明,让编译器知道存在 Foo
的第三个重载。所以这一次,调用表达式Foo(elem)
如期调用了第三个重载Foo
(因为它比Foo
的第一个重载更特殊)。
removing all namespaces
并且当所有东西都放在同一个全局命名空间中时,由于 ADL 也发现了第三个重载。
在编写模板方法时,我 运行 出现了以下行为,我不明白。
我有以下代码:
#include <array>
#include <iostream>
namespace A
{
template<typename T>
class Bar
{
T Var;
};
}
namespace B
{
template<typename T>
void Foo(const T& var)
{
std::cout << "default template method has been called" << std::endl << std::endl;
}
template<typename T, size_t N>
void Foo(const std::array<T,N>& var)
{
std::cout << "Array overload has been called" << std::endl;
for(auto& elem : var)
{
Foo(elem);
}
}
template<typename T>
void Foo(const A::Bar<T>& var)
{
std::cout << "Bar overload has been called" << std::endl << std::endl;
}
}
int main()
{
int VarInt;
A::Bar<int> VarBar;
std::array<int, 1> ArrayInt;
std::array<A::Bar<int>, 1> ArrayBar;
B::Foo(VarInt);
B::Foo(VarBar);
B::Foo(ArrayInt);
B::Foo(ArrayBar);
return 0;
}
它的输出不是我对 Bar 数组的预期,调用默认模板而不是 Bar 重载:
default template method has been called
Bar overload has been called
Array overload has been called
default template method has been called
Array overload has been called
default template method has been called
我注意到执行以下操作可以使编译器找到正确的重载:
- 删除所有名称空间或
- 在实现之前声明所有模板原型
It's output is not what i expect as with the array of Bar, the default template is called instead of the Bar overload
对于调用表达式 B::Foo(ArrayBar)
,选择第二个重载 void Foo(const std::array<T,N>& var)
,其中 N
推导为 1
,T
推导为 A::Bar<int>
.
现在在该重载中,当遇到调用表达式 Foo(elem)
时,编译器不知道第三个重载 Foo
。因此它选择 Foo
的第一个重载,这是当时可用的两个重载中最通用的。
declaring all the templates prototypes before implementing them
在实现 Foo
的所有重载之前提供它们的声明,让编译器知道存在 Foo
的第三个重载。所以这一次,调用表达式Foo(elem)
如期调用了第三个重载Foo
(因为它比Foo
的第一个重载更特殊)。
removing all namespaces
并且当所有东西都放在同一个全局命名空间中时,由于 ADL 也发现了第三个重载。