• Advertisement
Sign in to follow this  

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

This topic is 2186 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites
I just tested the code under g++ and it compiles fine. Strange... (using #include <memory> and -std=c++0x)

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement