Jump to content

  • Log In with Google      Sign In   
  • Create Account


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


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 aeroz   Members   -  Reputation: 171

Like
0Likes
Like

Posted 28 January 2012 - 10:44 AM

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!

Sponsor:

#2 aeroz   Members   -  Reputation: 171

Like
0Likes
Like

Posted 29 January 2012 - 09:36 AM

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.

#3 SiCrane   Moderators   -  Reputation: 9498

Like
1Likes
Like

Posted 29 January 2012 - 09:57 AM

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.

#4 aeroz   Members   -  Reputation: 171

Like
0Likes
Like

Posted 29 January 2012 - 11:11 AM

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?

#5 aeroz   Members   -  Reputation: 171

Like
0Likes
Like

Posted 29 January 2012 - 11:25 AM

Looks like I have to prefix it with boost::.

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

Thank you for the information!

#6 aeroz   Members   -  Reputation: 171

Like
0Likes
Like

Posted 29 January 2012 - 12:20 PM

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

#7 SiCrane   Moderators   -  Reputation: 9498

Like
1Likes
Like

Posted 29 January 2012 - 01:22 PM

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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS