Visual Studio namespace problem? (ambiguous call to boost::make_shared)

Started by
5 comments, last by SiCrane 12 years, 3 months ago
Hi! I'm having a strange problem that I hope you guys can help me understand.
I'm using Visual Studio 2010 SP1. The code compiles fine with the g++ compiler.
I tried to reproduce the problem with minimum code, but I was not yet able to get the error.

Here's my code:


SomeClass::SomeMethod()
{
using boost::make_shared;

// this does work:
make_shared<WidgetButton>( Rect(1,2,3,4), "hoi", boost::bind( &MainMenuState::onPressedButBack, this ), boost::bind( &MainMenuState::onPressedSound, this ) );

// this does not work: (produces the error below)
make_shared<WidgetButton>( Rect(1,2,3,4), "hoi", boost::bind( &MainMenuState::onPressedOpenLevel, this, "hoi" ), boost::bind( &MainMenuState::onPressedSound, this ) );

// this does work:
boost::make_shared<WidgetButton>( Rect(1,2,3,4), "hoi", boost::bind( &MainMenuState::onPressedOpenLevel, this, "hoi" ), boost::bind( &MainMenuState::onPressedSound, this ) );
}


VS gives me this:


1>..\src\game\states\MainMenuState.cpp(125): error C2668: 'boost::make_shared' : ambiguous call to overloaded function
1> C:\Libraries\boost_1_47\boost/smart_ptr/make_shared.hpp(330): could be 'boost::shared_ptr<T> boost::make_shared<WidgetButton,Rect,const char(&)[4],boost::_bi::bind_t<R,F,L>,boost::_bi::bind_t<R,boost::_mfi::mf0<R,MainMenuState>,boost::_bi::list1<A1>>>(Rect &&,A2,A3 &&,A4 &&)'
1> with
1> [
1> T=WidgetButton,
1> R=void,
1> F=boost::_mfi::mf1<void,MainMenuState,const std::string &>,
1> L=boost::_bi::list2<boost::_bi::value<MainMenuState *>,boost::_bi::value<const char *>>,
1> A1=boost::_bi::value<MainMenuState *>,
1> A2=const char (&)[4],
1> A3=boost::_bi::bind_t<void,boost::_mfi::mf1<void,MainMenuState,const std::string &>,boost::_bi::list2<boost::_bi::value<MainMenuState *>,boost::_bi::value<const char *>>>,
1> A4=boost::_bi::bind_t<void,boost::_mfi::mf0<void,MainMenuState>,boost::_bi::list1<boost::_bi::value<MainMenuState *>>>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xxshared(33): or 'std::tr1::shared_ptr<_Ty> std::tr1::make_shared<WidgetButton,Rect,const char(&)[4],boost::_bi::bind_t<R,F,L>,boost::_bi::bind_t<R,boost::_mfi::mf0<R,T>,boost::_bi::list1<A1>>>(_Arg0 &&,_Arg1,_Arg2 &&,_Arg3 &&)' [found using argument-dependent lookup]
1> with
1> [
1> _Ty=WidgetButton,
1> R=void,
1> F=boost::_mfi::mf1<void,MainMenuState,const std::string &>,
1> L=boost::_bi::list2<boost::_bi::value<MainMenuState *>,boost::_bi::value<const char *>>,
1> T=MainMenuState,
1> A1=boost::_bi::value<MainMenuState *>,
1> _Arg0=Rect,
1> _Arg1=const char (&)[4],
1> _Arg2=boost::_bi::bind_t<void,boost::_mfi::mf1<void,MainMenuState,const std::string &>,boost::_bi::list2<boost::_bi::value<MainMenuState *>,boost::_bi::value<const char *>>>,
1> _Arg3=boost::_bi::bind_t<void,boost::_mfi::mf0<void,MainMenuState>,boost::_bi::list1<boost::_bi::value<MainMenuState *>>>
1> ]
1> while trying to match the argument list '(Rect, const char [4], boost::_bi::bind_t<R,F,L>, boost::_bi::bind_t<R,F,L>)'
1> with
1> [
1> R=void,
1> F=boost::_mfi::mf1<void,MainMenuState,const std::string &>,
1> L=boost::_bi::list2<boost::_bi::value<MainMenuState *>,boost::_bi::value<const char *>>
1> ]
1> and
1> [
1> R=void,
1> F=boost::_mfi::mf0<void,MainMenuState>,
1> L=boost::_bi::list1<boost::_bi::value<MainMenuState *>>
1> ]


EDIT: the declaration of WidgetButton's constructor might be helpful for you:

WidgetButton( Rect area, const std::string& caption, boost::function0<void> clickedCallbackFunc, boost::function0<void> mouseOverCallbackFunc );


Nowhere I have "using namespace std;", so for me its weird that it tries to use "std::tr1::make_shared" and not "boost::make_shared".
The other weird thing is that when slightly modify the 3rd argument to the WidgetButton constructor (see code), it works...

As you can see I could just remove the using declaration and prepend boost:: to the make_shared call, but I want to understand why its not working.

Looking forward to your replies!
Advertisement
I was able to remove all the unimportant code from my project and got a minimal error producing example!


#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/function.hpp>
#include <string>

class A {
public:
A(boost::function0<void>) {}
};

void f() {}
void g(std::string) {}

int main() {
using boost::make_shared;
make_shared<A>( boost::bind(f) ); // no error
make_shared<A>( boost::bind(g, "hoi") ); // error
return 0;
}


Can you imagine why it doesn't compile?

The error is same as before:


1>c:\users\christian\documents\visual studio 2010\projects\minimalmakesharederror\main.cpp(18): error C2668: 'boost::make_shared' : ambiguous call to overloaded function
1> c:\libraries\boost_1_47\boost\smart_ptr\make_shared.hpp(198): could be 'boost::shared_ptr<T> boost::make_shared<A,boost::_bi::bind_t<R,F,L>>(A1 &&)'
1> with
1> [
1> T=A,
1> R=void,
1> F=void (__cdecl *)(std::string),
1> L=boost::_bi::list1<boost::_bi::value<const char *>>,
1> A1=boost::_bi::bind_t<void,void (__cdecl *)(std::string),boost::_bi::list1<boost::_bi::value<const char *>>>
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxshared(33): or 'std::tr1::shared_ptr<_Ty> std::tr1::make_shared<A,boost::_bi::bind_t<R,F,L>>(_Arg0 &&)' [found using argument-dependent lookup]
1> with
1> [
1> _Ty=A,
1> R=void,
1> F=void (__cdecl *)(std::string),
1> L=boost::_bi::list1<boost::_bi::value<const char *>>,
1> _Arg0=boost::_bi::bind_t<void,void (__cdecl *)(std::string),boost::_bi::list1<boost::_bi::value<const char *>>>
1> ]
1> while trying to match the argument list '(boost::_bi::bind_t<R,F,L>)'
1> with
1> [
1> R=void,
1> F=void (__cdecl *)(std::string),
1> L=boost::_bi::list1<boost::_bi::value<const char *>>
1> ]


Note that the error is only there when the argument type of g is in the std namespace.
It looks like this is a argument dependent lookup (ADL) issue (also called Koenig lookup). Basically, before resolving the name of a function call, the compiler looks up all the arguments to the function call. If those arguments use namespace X, namespace X is added to the possible namespaces to look at when resolving the name of the function call.

It looks like this is a argument dependent lookup (ADL) issue (also called Koenig lookup). Basically, before resolving the name of a function call, the compiler looks up all the arguments to the function call. If those arguments use namespace X, namespace X is added to the possible namespaces to look at when resolving the name of the function call.

Does that mean that Visual C++ is not standard compliant or is it the code?
Looks like I have to prefix it with boost::.

http://en.wikipedia.org/wiki/Argument-dependent_name_lookup#Criticism

Thank you for the information!
I just tested the code under g++ and it compiles fine. Strange... (using #include <memory> and -std=c++0x)
One of the fun details about boost::bind() is that it's return type is unspecified. This has a lot to do with the fact that it uses deep dark template magic that tends to crash some compilers, so boost uses #ifdef magic to make the return type different depending on the compiler to work around compiler issues. So on some compilers the type of the arguments of the bound function are part of the return type, thus pulling in those namespaces for ADL and on some compilers they aren't.

This topic is closed to new replies.

Advertisement