Related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49058 --- #include <functional> int main() { int i; std::bind([] (auto& x) {x = 1;}, i)(); } --- This is rejected because, during overload resolution, _Bind::operator() const's default template argument is spuriously instantiated.
Note that the instantiation is not spurious, but instead required by the core language. All overloads of _Bind::operator() are considered during the call to the forwarding call wrapper. While considering the const qualified overload the compiler is forced to instantiate the lambda to deduce the return type. This causes a error in a non-immediate context which causes the compile error.
Note that explicitly providing a return type for the lambda avoids this compile error. Example: --- #include <functional> int main() { int i; std::bind([] (auto& x) -> void {x = 1;}, i)(); // OK! } ---
Here is an example of why `_Bind::operator()(...) const` must be considered during overload resolution even if the call wrapper itself is not const. ------------------------------ #include <functional> struct Func { template <class ...Args> void operator()(Args&&...) = delete; template <class ...Args> void operator()(Args&&...) const {} }; int main() { Func f; std::bind(f)(); } -------------------------
(In reply to Eric Fiselier from comment #3) > Here is an example of why `_Bind::operator()(...) const` must be considered > during overload resolution even if the call wrapper itself is not const. > > ------------------------------ > #include <functional> > > struct Func { > template <class ...Args> > void operator()(Args&&...) = delete; > > template <class ...Args> > void operator()(Args&&...) const {} > }; > > int main() { > Func f; > std::bind(f)(); > } > ------------------------- Interesting, libstdc++ rejects this as an attempt to call a deleted function. That seems more correct than libc++'s approach which calls the const overload.
See also the discussion on Phabricator: https://reviews.llvm.org/D32824 I agree; AFAICS [func.bind.bind] is clear on this: the type of the Func object used to call the member operator() is non-const. On 5/4/2017 9:09 PM, rs2740 at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80564 > > TC <rs2740 at gmail dot com> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > CC| |rs2740 at gmail dot com > > --- Comment #4 from TC <rs2740 at gmail dot com> --- > (In reply to Eric Fiselier from comment #3) >> Here is an example of why `_Bind::operator()(...) const` must be considered >> during overload resolution even if the call wrapper itself is not const. >> >> ------------------------------ >> #include <functional> >> >> struct Func { >> template <class ...Args> >> void operator()(Args&&...) = delete; >> >> template <class ...Args> >> void operator()(Args&&...) const {} >> }; >> >> int main() { >> Func f; >> std::bind(f)(); >> } >> ------------------------- > Interesting, libstdc++ rejects this as an attempt to call a deleted function. > That seems more correct than libc++'s approach which calls the const overload. >
(In reply to TC from comment #4) > (In reply to Eric Fiselier from comment #3) > > Here is an example of why `_Bind::operator()(...) const` must be considered > > during overload resolution even if the call wrapper itself is not const. > > > > ------------------------------ > > #include <functional> > > > > struct Func { > > template <class ...Args> > > void operator()(Args&&...) = delete; > > > > template <class ...Args> > > void operator()(Args&&...) const {} > > }; > > > > int main() { > > Func f; > > std::bind(f)(); > > } > > ------------------------- > > Interesting, libstdc++ rejects this as an attempt to call a deleted > function. That seems more correct than libc++'s approach which calls the > const overload. See also the discussion on Phabricator: https://reviews.llvm.org/D32824 I agree. AFAICS [func.bind.bind] is clear on this: the type of the Func object used to call the member operator() is non-const.
Oh, damn. "Submit only my new comment" does not what I thought it does. :-)