扣除模板时,合格和不合格的名称查找有什么区别?

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 推导为 1T 推导为 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 也发现了第三个重载。