c++ - Difference between "explicit" and "implicit" invocation of operator () -
is there clause in standard describing following difference between ways call operator ()
base classes?
#include <iostream> #include <type_traits> #include <cstdlib> #include <cassert> template< typename visitor, typename ...visitors > struct composite_visitor : std::decay_t< visitor > , composite_visitor< visitors... > { //using std::decay_t< visitor >::operator (); //using composite_visitor< visitors... >::operator (); composite_visitor(visitor && _visitor, visitors &&... _visitors) : std::decay_t< visitor >(std::forward< visitor >(_visitor)) , composite_visitor< visitors... >{std::forward< visitors >(_visitors)...} { ; } }; template< typename visitor > struct composite_visitor< visitor > : std::decay_t< visitor > { //using std::decay_t< visitor >::operator (); composite_visitor(visitor && _visitor) : std::decay_t< visitor >(std::forward< visitor >(_visitor)) { ; } }; template< typename visitor, typename ...visitors > composite_visitor< visitor, visitors... > compose_visitors(visitor && _visitor, visitors &&... _visitors) { return {std::forward< visitor >(_visitor), std::forward< visitors >(_visitors)...}; } int main() { struct {}; struct b {}; #if 1 struct { int operator () (a) { return 1; } } x; struct { int operator () (b) { return 2; } } y; auto xy = compose_visitors(x, y); #else auto xy = compose_visitors([] (a) { return 1; }, [] (b) { return 2; }); #endif // "implicit": assert(xy(a{}) == 1); assert(xy(b{}) == 2); // "explicit": assert(xy.operator () (a{}) == 1); // error: member 'operator()' found in multiple base classes of different types assert(xy.operator () (b{}) == 2); return exit_success; }
"implicit" invocation compiles fine, not "explicit". why so?
compose_visitors
combine arguments single class means of construction of class derived of them.
uncommenting using
derectives removes hard error. clear.
the behaviour identical lambda functions , functors.
compiler clang 3.6.
the "implicit" invocation ill-formed. in fact, gcc rejects it, seems bug in clang.
the standard (n4140, [over.call]/1) says that
a call
x(arg1,...)
interpretedx.operator()(arg1, ...)
class objectx
of typet
ift::operator()(t1, t2, t3)
exists , if operator selected best match function overload resolution mechanism (13.3.3).
so 2 invocations must behave identically.
update: known issue in clang.
Comments
Post a Comment