[PATCH] D32824: [libc++] Use placeholder return types to avoid hard errors during overload resolution

Robert Haberlach via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed May 3 16:31:52 PDT 2017


Arcoth added a comment.

In https://reviews.llvm.org/D32824#745392, @EricWF wrote:

> This change regresses other code. By changing `__bind_return<...>::type` into `decltype(auto)` you prevent the member functions from SFINAE'ing. For example:
>
>   #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)(); // Broken after your change.
>   }
>
>
> This patch cannot introduce regressions but changing to using `decltype(auto)` does. I'm not sure the behavior you want is possible. The library is required to evaluate the validity of calling the specified functor in the signature of the call operator in order to correctly SFINAE.
>  I think this makes accepting the code in PR32856 impossible.


This is **intended **to fail (as I also mentioned in the motivating SO post <http://stackoverflow.com/a/43696236/3647361>). The type of the object argument `fd` is `FD`, where `FD `is `decay_t<Func>`, i.e. `Func`. That's it. And if we use a non-`const ` object argument, overload resolution prefers non-`const` member functions per se, hence we should get a diagnostic saying that a deleted function is called. Alternatively, some other construct inside `bind` should fail: libstdc++'s `bind` somehow requires `result_of_t<Func&()>`, which fails.

In short, this was never intended to work; the fact that it does is a consequence of the return type being denoted in an expression SFINAE manner.


https://reviews.llvm.org/D32824





More information about the cfe-commits mailing list