Linux gcc picking 试图实例化一个模板,其中函数应该是

Linux gcc picking trying to instantiate a template where function should be

我有以下重现错误的示例代码:

// non-namespacing this compiles as expected
namespace n
{
    template <typename T>
    void foo(T const & t)
    {
        t.doesnt_have_this_method();
    }
}

template <typename T>
void bar(T const & t)
{
    // picks the template over the overload
    n::foo(t);
}

namespace n
{
    // function overload
    void foo(int const &);
}

void n::foo(int const &) {}


int main()
{
    int a;

    bar(a);
}

该代码在 MSVC 2010 和 Solaris 8 编译器上都能正常编译。 但是 gcc4 (GCC) 4.1.2 20071124 (Red Hat 4.1.2-42) 失败并出现错误:

test.cpp: In function 'void n::foo(const T&) [with T = int]':
test.cpp:14:   instantiated from 'void bar(const T&) [with T = int]'
test.cpp:34:   instantiated from here
test.cpp:6: error: 'const int' has no member named 'doesnt_have_this_method'

模板 bar 似乎没有看到 foo 函数重载。我想弄清楚为什么会这样。我知道的三件事可以缓解这个问题,但很难在生产环境中执行:

  1. bar 之前声明 foo(int const &)。这是我可以在我的产品代码中做的事情,但将来很难在整个代码库中强制执行
  2. 未将 foo 放入命名空间。这是我不能做的事情,因为我正在与另一个库交互。
  3. 使重载成为模板特化 template<> void n::foo(int const &)。我不能做的事情,因为 foo(int const &) 的声明不在我的控制范围内。

请帮助我了解如何解决此问题。为什么编译器没有选择正确的函数?

bar 的定义中,唯一可见的 foo 是函数模板,因为另一个尚未声明。