4

In C++ we can omit namespace qualification in case of using function that takes, as its first argument, object of type declared in the same namespace as our function. However, I've noticed that this doesn't work with templated functions (like std::get). I wrote simple example to confirm that this is really related to templates:

namespace ns {

    struct S {};

    void sFoo(const S&) {}
    template<typename T> void sBar(const S&) {}
}

void foo()
{
    ns::S s;
    sFoo(s); // ok
    sBar<int>(s); // error: ‘sBar’ was not declared in this scope
    ns::sBar<int>(s); // ok
}

I tried explicit instantiation, but it didn't change anything (even if it would, it would be worse option than just using using).

So why exacly can't I call templated function without specifying its namespace (and assuming neither using nor using namespace directives)?

witosx
  • 614
  • 4
  • 15

1 Answers1

2

sBar is not a function, but a function template. The argument-dependent lookup only works for function names. It's true that sBar<int> is a function, but you can't instantiate the template if you don't know its proper name!

Unrelatedly, if the template argument can be deduced, that ADL does work:

namespace ns
{
    template <typename T> void sZip(T &) { }
}

void foo()
{
    ns::S s;
    sZip(s);  // OK, deduces T = ns::S
}

The general "best-practice" for C++ is to make function templates only if the arguments can be deduced, and to never specify the arguments explicitly. (Exceptions to this rule are std::forward and various make_* functions that require one mandatory argument for the desired result type.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084