Question

I have a question relating to how types are found by ADL in generic situations. Specifically, I have some 'generic' code where I need to check at compile-time for the presence of a function which should be found by ADL. For example:

#include "MyClass.h"
struct MyClass
{
    friend inline void DoSomething(MyClass& first, MyClass& second){} 
}

MyClass a, b;
DoSomething(a,b); //DoSomething in MyClass will be found by ADL

I have a trait class which uses the 'sizeof trick' to check for the presence of this ADL function:

//HasDoSomething.h
//type trait to check whether a type has a DoSomething function defined 
template<typename T>                                
struct has_doSomething
{                                                      
    typedef char yes;   
    typedef char (&no)[2];

    //SFINAE eliminates this when the type is invalid
    template <typename U, U> 
    struct Check; 

    template <typename U> 
    static yes Tester(Check<void(*)(U&, U&), &DoSomething>*);

    //overload resolution prefers anything at all over ...
    template <typename U> static no Tester(...);

    static bool const value = sizeof(Tester<T>(0)) == sizeof(yes);    
};  

The trait class/sizeof trick itself is not important (you can find details in the book C++ Template Metaprogramming, from which I lifted it, if you're interested). Rather, the issue is that this type trait will not compile unless I either #include it after the #include of a (arbitrary) type which does have a DoSomething defined, e.g.,

#include "MyClass.h"
#include "HasDoSomething.h"

or alternatively I create a dummy class with a DoSomething function declaration:

struct DummyClass
{
public:
    friend inline void DoSomething(DummyClass&, DummyClass&);
private:
    DummyClass(){}
};

and include that (either directly or via Dummy.h) into HasDoSomething.h. It doesn't seem ideal to have to kick ADL lookup like this by either mandating order of #includes or by inserting redundant code, so am I misunderstanding something or doing something wrong?

Was it helpful?

Solution

ADL is only used for determining the overload-set of a function call.
Before the compiler can do that, it has to determine that is is a function call in the first place, by doing normal name-lookup and finding a function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top