GNOME Bugzilla – Bug 306705
Can't overload methods based on different slot<> parameters.
Last modified: 2018-07-11 07:28:48 UTC
Version details: 2.0.10 Distribution/Version: Debian The following code fails to compile with the following error message: mfowles@fowles:~/test$ cat ambiguous.cpp #include <sigc++/slot.h> void use(const sigc::slot1<void, int>& s) { s(2); } void use(const sigc::slot0<void>& s) { s(); } void dummy(int a) { a++; } int main(int argc, char** argv) { use(sigc::ptr_fun(dummy)); return 0; } mfowles@fowles:~/test$ gcc ambiguous.cpp `pkg-config --cflags sigc++-2.0` ambiguous.cpp: In function `int main(int, char**)': ambiguous.cpp:8: error: call of overloaded `use(sigc::pointer_functor1<int, void>)' is ambiguous ambiguous.cpp:3: error: candidates are: void use(const sigc::slot1<void, int>&) ambiguous.cpp:4: error: void use(const sigc::slot0<void>&) mfowles@fowles:~/test$ This can eventually be traced back to the templated constructor for sigc::slot1 and sigc::slot0. One might be able to solve this by having a functor_baseN class which all functors of N arguments inherit from and then providing a constructor for slotN which takes a functor_baseN argument. I am not deeply familiar with the code base however, so this might not be simple or correct. One can explicitely construct the slot they want as a workaround, but extra typing always sucks.
Did this work with previous versions of libsigc++? I think it's always been this way.
I don't know. I would guess that it has always been this way, but I am very unfamiliar with sigc++.
[Resetting QA Contact and Assignee to default - see bug 659799 for more info]
Created attachment 273479 [details] [review] patch: Improve the possibility to overload functions with slot parameters Like Matt has noticed in the bug description, the problem is the constructor template <class T_functor> slot(const T_functor& _A_func); The declaration gives the impression that a slot can be constructed from any other type. That's not really true, but the compiler detects that only when it tries to instantiate the constructor and digs into its definition. Overload resolution only considers function declarations, not definitions. My patch tries to eliminate this constructor when instantiation would fail. It succeeds only partially. In many cases it fails when the constructor parameter is a sigc adaptor. These adaptors have templated function call operators whose declarations accept any number of parameters of any type. The patch requires a compiler with C++11 support. It's probably too early to push it. I'm not even sure it should ever be pushed. I leave it here, hoping that someone can improve on it. Since there is a fairly easy workaround for the problem, a solution is not really important. Workaround: In the code in comment 0, replace use(sigc::ptr_fun(dummy)); by use(sigc::slot<void, int>(sigc::ptr_fun(dummy))); Then the parameter is an exact match of one of overloaded use() functions. > One might be able to solve this by having a functor_baseN > class which all functors of N arguments inherit from and then providing a > constructor for slotN which takes a functor_baseN argument. I have not studied such a solution very closely, but I suspect that it would also at best be a partial solution. What if the overloaded slots take the same number of parameters, but with different types? And what about the adaptors that pretend to accept any number of parameters? Probably they must be split into different classes that derive from adaptor_baseN. Of course C++11 did not exist, when this bug was filed. I think that libsigc++ can make much use of C++11. E.g. the code can probably shrink quite a lot with variadic templates. And sigc::is_base_and_derived<> can be replaced by std::is_base_of<>. I don't volunteer for a complete rewrite of libsigc++.
This slightly-updated test case is for both sigc++-2.0 and sigc++-3.0: #include <sigc++/slot.h> void use(const sigc::slot<void, int>& s) { s(2); } void use(const sigc::slot<void>& s) { s(); } void dummy(int a) { a++; } int main(int argc, char** argv) { use(sigc::ptr_fun(dummy)); return 0; } We see much the same error message with libsigc++-3.0: $ g++ test_different_slot_params.cc --std=c++14 `pkg-config sigc++-3.0 --libs --cflags` test_different_slot_params.cc: In function ‘int main(int, char**)’: test_different_slot_params.cc:8:29: error: call of overloaded ‘use(sigc::pointer_functor<void, int>)’ is ambiguous use(sigc::ptr_fun(dummy)); ^ test_different_slot_params.cc:3:6: note: candidate: void use(const sigc::slot<void, int>&) void use(const sigc::slot<void, int>& s) { s(2); } ^ test_different_slot_params.cc:4:6: note: candidate: void use(const sigc::slot<void>&) void use(const sigc::slot<void>& s) { s(); } ^ and with clang++: $ clang++ test_different_slot_params.cc --std=c++14 `pkg-config sigc++-3.0 --libs --cflags` test_different_slot_params.cc:8:5: error: call to 'use' is ambiguous use(sigc::ptr_fun(dummy)); ^~~ test_different_slot_params.cc:3:6: note: candidate function void use(const sigc::slot<void, int>& s) { s(2); } ^ test_different_slot_params.cc:4:6: note: candidate function void use(const sigc::slot<void>& s) { s(); } ^ 1 error generated. Would you like to put something like this in libsigc++-3.0 (in the variadic_bind4 branch, at least today) with a suitable test?
I'm not very fond of my patch in comment 4. It's a complicated partial fix of a small problem with an easy workaround. I suggest that we don't implement it unless someone insists that it's really helpful. If you do push it, change the method name check() to something else. I learned from bug 759315 that check() can be a preprocessor macro in Mac OS X.
According to https://libsigcplusplus.github.io/libsigcplusplus/devel.html the issue tracker of libsigc++ is located at https://github.com/libsigcplusplus/libsigcplusplus/issues nowadays. If the problem in this bug report still exists in a recent version of libsigc++ please file this bug report in GitHub. Closing this report as WONTFIX as part of Bugzilla Housekeeping, as we plan to shut down GNOME Bugzilla in favor of GNOME Gitlab.
WONTFIX is the right resolution for this bug report. See a short descussion at https://mail.gnome.org/archives/libsigc-list/2018-March/msg00003.html especially the last few lines. The reported problem probably still exists, but it equally probably will never be fixed.