Search code examples
c++templatesoverload-resolution

Is it possible to defer overload resolution?


I was experimenting with overloads

int foo(int,int);
int foo(int);

int main() {           
    //decltype(foo) x;  // error: reference to overloaded function could not be resolved;
    decltype(foo(1)) f;      
}

I know that I cannot get a pointer to foo unless I pick one of the overloads, but I wonder why do overload sets have no type? Wouldnt it be natural to write

template <typename F>
void foofoo(F f,bool x) {
    if (x) f(1);
    else f(1,0);
}

and call it as foofoo(foo,true); ? I know that there are different ways to write something like that, but I specifically wonder about overload sets. Anyhow, my question is

Is there anything I can do with an overload set before picking one of the overloads?

In other words, is there some magic that would make the following true literally as is?

std::is_same_v< decltype( foo(1,1) ), magic<foo,int,int>::type >;

Or is this generally not possible, because foo is unresolved?


Solution

  • There are very few things you can do with the name of an overloaded function set that don't immediately require resolving to one specific function (or function template specialization). But one context where many semantic checks get "delayed" in a way is inside a template. And a generic lambda is a shortcut way of writing a template. So one thing we can do is:

    #include <utility>
    
    #define WRAP_OVERLOADS(f) [](auto&& ...args) { \
        return f(std::forward<decltype(args)>(args)...); }
    
    int foo(int, int);
    int foo(int);
    
    int main() {
        auto f = WRAP_OVERLOADS(foo);
        f(1);
        f(2,3);
    }
    

    Though the preprocessor #define is required because there's no way to represent the name of the function to call to pass to a template. (A function pointer can be a template argument or can help deduce the type of a template function parameter, but then you're back to needing one specific overload to use the template.)