
The following short program works fine for VC7.1, but for several well regarded compilers including Intel-8/9 and gcc-3.4 fails to compile due to "ambiguous overload" errors. It's causing errors in the TR1/Bind concept tests, and I'd like to figure out if it's the compiler or Boost.Bind that's at fault so I can file defect reports with the compiler vendors if necessary. Here's the test case: #include <boost/bind.hpp> template <class Functor> void consume(Functor f); double test_proc(int a, char b, long c) { return a+b+c; } struct from_double { from_double(double){} }; int main() { consume(boost::bind<double>(&test_proc, 0, 0, 0)); consume(boost::bind<float>(&test_proc, 0, 0, 0)); consume(boost::bind<long double>(&test_proc, 0, 0, 0)); consume(boost::bind<from_double>(&test_proc, 0, 0, 0)); } And a typical error message from Intel-9 is: $ icl -GX -c -Ic:\\data\\boost\\develop\\boost bind.cpp Intel(R) C++ Compiler for 32-bit applications, Version 9.0 Build 20050912Z Pa ckage ID: W_CC_C_9.0.024 Copyright (C) 1985-2005 Intel Corporation. All rights reserved. 30 DAY EVALUATION LICENSE bind.cpp bind.cpp(21): error: more than one instance of overloaded function "boost::bind" matches the argument list: function template "boost::bind<R,F,A1,A2,A3>(F, A1, A2, A3)" function template "boost::bind(R (*)(B1, B2, B3), A1, A2, A3)" argument types are: (double (*)(int, char, long), int, int, int) consume(boost::bind<double>(&test_proc, 0, 0, 0)); ^ compilation aborted for bind.cpp (code 2) Note that it's the presence of the function pointer overloads that causes the error: in other words it's an artefact of the implementation that causes the error, not the TR1 specification itself. Anyone any ideas whose at fault here? Thanks, John.

John Maddock wrote:
bind.cpp(21): error: more than one instance of overloaded function "boost::bind" matches the argument list:
function template "boost::bind<R,F,A1,A2,A3>(F, A1, A2, A3)"
function template "boost::bind(R (*)(B1, B2, B3), A1, A2, A3)"
argument types are: (double (*)(int, char, long), int, int, int)
The compilers are right, unfortunately. Function template partial ordering doesn't take into account the supplied template arguments, <double> in this case.

John Maddock wrote:
The compilers are right, unfortunately. Function template partial ordering doesn't take into account the supplied template arguments, <double> in this case.
Oh shucks, OK I'll have to document that as a non-conformity in the Tr1 docs.
The upside (in addition to supporting legacy compilers) is that you can do this: void f( int ); // #1 void f( int, int ); // #2 int main() { boost::bind( f, 1 ); // chooses #1 boost::bind( f, 1, 2 ); // chooses #2 }

John Maddock writes:
The upside (in addition to supporting legacy compilers) is that you can do this:
void f( int ); // #1 void f( int, int ); // #2
int main() { boost::bind( f, 1 ); // chooses #1 boost::bind( f, 1, 2 ); // chooses #2 }
Ah, that's neat.
I actually consider this to be a vital usability feature. It would be an unpleasant surprise if it's not going to make it into comforming TR1 implementations. Or did I misunderstand your earlier comment? -- Aleksey Gurtovoy MetaCommunications Engineering

I actually consider this to be a vital usability feature. It would be an unpleasant surprise if it's not going to make it into comforming TR1 implementations. Or did I misunderstand your earlier comment?
I don't know if it's possible to support this, and to support the named-return-type syntax as well. I also don't see anything in the TR1 text that requires this to be supported... Peter? John.

John Maddock wrote:
I actually consider this to be a vital usability feature. It would be an unpleasant surprise if it's not going to make it into comforming TR1 implementations. Or did I misunderstand your earlier comment?
I don't know if it's possible to support this, and to support the named-return-type syntax as well.
It's possible with some enable_if tricks. One needs to eliminate the R/F overload when F is a function pointer that returns R and is covered by one of the additional overloads.
I also don't see anything in the TR1 text that requires this to be supported... Peter?
It's not required in TR1. It is up to the implementation to make bind "just do the right thing" in such situations: overloaded functions where it's possible to disambiguate, nonstandard calling conventions, extern "C", nonstandard function object extensions.

Peter Dimov writes:
John Maddock wrote:
I actually consider this to be a vital usability feature. It would be an unpleasant surprise if it's not going to make it into comforming TR1 implementations. Or did I misunderstand your earlier comment?
I don't know if it's possible to support this, and to support the named-return-type syntax as well.
It's possible with some enable_if tricks. One needs to eliminate the R/F overload when F is a function pointer that returns R and is covered by one of the additional overloads.
I also don't see anything in the TR1 text that requires this to be supported... Peter?
It's not required in TR1. It is up to the implementation to make bind "just do the right thing" in such situations: overloaded functions where it's possible to disambiguate, nonstandard calling conventions, extern "C", nonstandard function object extensions.
Thanks for the clarification! IMO this list is worth putting into our TR1 bind docs, so that users have more chances to make an educated choice between "native" and Boost bind implementation. -- Aleksey Gurtovoy MetaCommunications Engineering
participants (3)
-
Aleksey Gurtovoy
-
John Maddock
-
Peter Dimov