Question:
I saw now that in the 17th standard there is a new template function std::invoke
. I was very happy, because I thought it was the same invoke
as in .NET , but after looking for information about it, I still did not fully understand why it was needed. I understand that it calls functors and lambdas, but how does this differ from their direct call? Can std::invoke
make this call in a certain thread, as its counterpart from .NET can do?
Answer:
The std::invoke
to call regular methods and non-static methods of a class in a uniform manner. This is primarily useful when writing templates. For example, here's a compact function template that wraps a call to another function:
template<typename F, typename V1, typename V2> auto
foo(F f, V1 v1, V2 v2) -> void
{
::std::invoke(f, v1, v2);
}
Usage example:
inline auto
bar(int v1, int v2) -> void
{
::std::cout << v1 << " " << v2 << ::std::endl;
}
class Bar
{
private: int m_v;
public: explicit
Bar(int v): m_v{v} {}
public: auto
bar(int v2) -> void
{
::std::cout << m_v << " " << v2 << ::std::endl;
}
};
int
main()
{
int v1{12};
int v2{23};
foo(&bar, v1, v2); // вызов обычного метода
Bar b{12};
foo(&Bar::bar, b, v2); // вызов нестатического метода класса по ссылке
foo(&Bar::bar, &b, v2); // вызов нестатического метода класса по указателю
}
Without using ::std::invoke
would have to independently implement options for calling non-static class methods:
template<typename F, typename V1, typename V2> auto
foo(F f, V1 v1, V2 v2) -> ::std::enable_if_t
<
not ::std::is_member_function_pointer_v<F>
>
{
f(v1, v2);
}
template<typename F, typename V1, typename V2> auto
foo(F f, V1 v1, V2 v2) -> ::std::enable_if_t
<
::std::is_member_function_pointer_v<F> and not ::std::is_pointer_v<V1>
>
{
(v1.*f)(v2);
}
template<typename F, typename V1, typename V2> auto
foo(F f, V1 v1, V2 v2) -> ::std::enable_if_t
<
::std::is_member_function_pointer_v<F> and ::std::is_pointer_v<V1>
>
{
(v1->*f)(v2);
}