Search code examples
c++templatesnamespacesargument-dependent-lookup

C++ weird templates/namespaces behavior


I had a problem compiling my code since it wasn't able to find a matching function on a template. I've narrowed down the problem to this example:

namespace cv
{
    class FileNode
    { };

    template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)
    {
        read(n, value, _Tp());
    }

    static inline void read(const FileNode& node, bool& value, bool default_value)
    { }
}

class K
{   };

namespace D
{
    class A
    { };
}

template<class X>
static void read(const cv::FileNode& node, X& x, const X& default_value)
{
    return;
}

using namespace D;
class B
{
    void read(const cv::FileNode& fn)
    {
        A a;
        fn >> a;
    }
};

int main(int argc, char* argv[]) { }

On Gcc 9.10 I get the following error:

invalid initialization of reference of type 'bool&' from expression of type 'D::A'  { read(n, value, _Tp()); }

On Visual Studio 2019:

Error   C2664    'void cv::read(const cv::FileNode &,bool &,bool)': cannot convert argument 2 from '_Tp' to 'bool &'

I've found any of the following changes will make the code compiling:

  • class A -> class A : public K
  • Delete read specialization for bool
  • Remove cv namespace
  • Move the read template inside namespace D

Unfortunately, none of the previous fixes is applicable to my original problem and I still don't really have an actual understanding on why exactly it's not able to find the read template.


Solution

  • ADL strikes back:

    in

    template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)
    {
        read(n, value, _Tp());
    }
    

    read is undeclared, so can only be found by ADL

    So it will search in namespace associated to FileNode (so cv), and the ones associated to _Tp.

    when _Tp is D::A, it would be namespace D.

    and the only possible overload of read is cv::read which take bool.

    Moving declaration of read<T> above cv::operator >> solve the issue at it would also be considered with ADL.

    Demo