Search code examples
c++boostoverloadingboost-function

Boost Overload strange behaviour.. how `int (int ), int (std::string )` differs from `int (int ), int (std::string ), std::string (std::string)`?


So there is that great lib called OverLoad (link to downloadable svn directory, lib is header only). it can accept functions of any types into it and automatically decide which one you are calling. It is like boost function but better. Here are 2 code samples (browser can view boost svn) one two. and here is my code that does not compile and is based on them:

#include <string>

#include <boost/detail/lightweight_test.hpp>

#include <boost/overload.hpp>

using boost::overload; 

template<class out, class in>
out foo(in O )
{
    std::cout << "yes we can!";
    return out();
}

int main()
{
    //// works
    //overload<int (int ), int (std::string )> f;
    //// works
    //int (*foo1) (int ) = &foo<int, int>;
    //int (*foo2) (std::string ) = &foo<int, std::string>;
    //f.set(foo1);
    //f.set(foo2);
    // or we can use
    //// does also work
    //f.set<int (int )>(&foo<int, int>);
    //f.set<int (std::string )>(&foo<int, std::string>);
    ////

    overload<int (int ), int (std::string ), std::string (std::string) > f;
    //// but when we do this
    //f.set<int (int )>(&foo<int, int>);
    //f.set<int (std::string )>(&foo<int, std::string>);
    //f.set<int (std::string )>(&foo<std::string, std::string>);
    //// or this:
    int (*foo1) (int ) = &foo<int, int>;
    int (*foo2) (std::string ) = &foo<int, std::string>;
    std::string (*foo3) (std::string ) = &foo<std::string, std::string>;
    f.set(foo1);
    f.set(foo2);
    f.set(foo3);
    //// we get compile error

    BOOST_ASSERT( f(0) == 1 );
    BOOST_ASSERT( f("hi") == 2 ); // here we get Error  1   error C3066: there are multiple ways that an object of this type can be called with these arguments

    return boost::report_errors();
}

So I wonder how to get around this issue?


Solution

  • Overload resolution only considers the parameter types; it does not consider the return type. So, during overload resolution, int (std::string) is indistinguishable from std::string(std::string).

    Since this library has to rely on the C++ language's overloading capabilities, it too cannot distinguish between the two functions.