Namespaces
Variants
Views
Actions

Talk:cpp/utility/functional/invoke

From cppreference.com

[edit] Problems with the possible implementation

First, it doesn't SFINAE, while the standard signature is SFINAE-friendly (due to the use of std::result_of_t).

Second, expression SFINAE is applied too liberally. For example, the following should hit the first bullet point and be ill-formed, but in the implementation hit the second bullet point instead.

struct Bar { void bar(); };
struct Foo : private Bar { Bar& operator *(); };
invoke(&Bar::bar, Foo());

Similarly, invoke(PMD_that_is_a_function_object, Class, Arguments) should be ill-formed but isn't. T. Canens (talk) 02:32, 23 September 2015 (PDT)

My bad. I did notice the accept-invalid problem when I ported the implementation of INVOKE from cpp/types/result_of, but I thought the solution using std::enable_if would make the possible implementation longer and uglier (it is already quite long), so I did not attempt to solve this problem. After all, this should be solvable. --D41D8CD98F (talk) 05:32, 23 September 2015 (PDT)

[edit] Redundant trailing return types

Maybe it is more desirable to remove trailing return types from INVOKE-helpers due to redundancy? Secondly, what is a reason of duplicating these quite complicated lines of code? — Preceding unsigned comment added by I7achi (talkcontribs)

They are absolutely required for expression SFINAE. Without them the call will be a completely ambiguous mess. T. Canens (talk) 10:19, 1 November 2015 (PST)
What about return type deduction (cpp/language/function) which was introduced since C++14? I could be wrong, of course, but can you provide short SFINAE example where omitting trailing return type results in ambiguity? Thank you in advance --I7achi (talk) 12:46, 1 November 2015 (PST)
Deduced return types do not SFINAE; an invalid expression results in a hard error. T. Canens (talk) 13:03, 1 November 2015 (PST)
Ok, I got it. --I7achi (talk) 13:44, 1 November 2015 (PST)

[edit] What is the reason of specifying noexcept twice?

Why in the possible implementation the noexcept operator specified two times? For example:

constexpr auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args)
   /* --> */ noexcept(noexcept( /* <-- */
(std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)))

Thanks in advance for any informative reply!

And it will be very useful for newbies (and for me, too :D) to add short comments, that describe the purpose of each specialization of the INVOKE. Because, IMHO this is quite untrivial template, doesn't it? I7achi (talk) 15:30, 15 March 2016 (PDT)

The first one introduces a noexcept-specification; the second one is the noexcept operator. T. Canens (talk) 17:41, 15 March 2016 (PDT)
Thank you very much! This brings me clarity in the question. I7achi (talk) 19:00, 15 March 2016 (PDT)