std::invoke(C++1z) 是如何工作的?
How does std::invoke(C++1z) work?
namespace detail {
template <class F, class... Args>
inline auto INVOKE(F&& f, Args&&... args) ->
decltype(std::forward<F>(f)(std::forward<Args>(args)...)) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
template <class Base, class T, class Derived>
inline auto INVOKE(T Base::*pmd, Derived&& ref) ->
decltype(std::forward<Derived>(ref).*pmd) {
return std::forward<Derived>(ref).*pmd;
}
template <class PMD, class Pointer>
inline auto INVOKE(PMD pmd, Pointer&& ptr) ->
decltype((*std::forward<Pointer>(ptr)).*pmd) {
return (*std::forward<Pointer>(ptr)).*pmd;
}
template <class Base, class T, class Derived, class... Args>
inline auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args) ->
decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)) {
return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
}
template <class PMF, class Pointer, class... Args>
inline auto INVOKE(PMF pmf, Pointer&& ptr, Args&&... args) ->
decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)) {
return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...);
}
} // namespace detail
template< class F, class... ArgTypes>
decltype(auto) invoke(F&& f, ArgTypes&&... args) {
return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...);
}
我从这里看到上面的实现:
http://en.cppreference.com/w/cpp/utility/functional/invoke
然后我想知道编译器如何匹配所需的确切版本。 SFINAE 是否适用于尾随 return 类型?
does SFINAE work on tailing return type?
是的。尾随的 return 类型语法不会启用任何新功能,它只是使编写某些依赖于参数类型的 return 类型的情况变得更容易。
template <class F, class... Args>
inline auto INVOKE(F&& f, Args&&... args) ->
decltype(std::forward<F>(f)(std::forward<Args>(args)...) { ... }
可以等效地写成
template <class F, class... Args>
inline decltype(std::forward<F>(std::declval<F&>())(std::forward<Args>(std::declval<Args&>())...))
INVOKE(F&& f, Args&&... args) { ... }
例如,其他的都一样。这可以简化,但即使您简化了它,return 类型不能使用与 return
表达式相同的语法这一事实也很难理解发生了什么。因此有了新的语法。
SFINAE 唯一不起作用的情况是推导的 return 类型。他们也使用 auto
,但禁用 SFINAE 的并不是 auto
关键字本身。
namespace detail {
template <class F, class... Args>
inline auto INVOKE(F&& f, Args&&... args) ->
decltype(std::forward<F>(f)(std::forward<Args>(args)...)) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
template <class Base, class T, class Derived>
inline auto INVOKE(T Base::*pmd, Derived&& ref) ->
decltype(std::forward<Derived>(ref).*pmd) {
return std::forward<Derived>(ref).*pmd;
}
template <class PMD, class Pointer>
inline auto INVOKE(PMD pmd, Pointer&& ptr) ->
decltype((*std::forward<Pointer>(ptr)).*pmd) {
return (*std::forward<Pointer>(ptr)).*pmd;
}
template <class Base, class T, class Derived, class... Args>
inline auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args) ->
decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)) {
return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
}
template <class PMF, class Pointer, class... Args>
inline auto INVOKE(PMF pmf, Pointer&& ptr, Args&&... args) ->
decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)) {
return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...);
}
} // namespace detail
template< class F, class... ArgTypes>
decltype(auto) invoke(F&& f, ArgTypes&&... args) {
return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...);
}
我从这里看到上面的实现:
http://en.cppreference.com/w/cpp/utility/functional/invoke
然后我想知道编译器如何匹配所需的确切版本。 SFINAE 是否适用于尾随 return 类型?
does SFINAE work on tailing return type?
是的。尾随的 return 类型语法不会启用任何新功能,它只是使编写某些依赖于参数类型的 return 类型的情况变得更容易。
template <class F, class... Args>
inline auto INVOKE(F&& f, Args&&... args) ->
decltype(std::forward<F>(f)(std::forward<Args>(args)...) { ... }
可以等效地写成
template <class F, class... Args>
inline decltype(std::forward<F>(std::declval<F&>())(std::forward<Args>(std::declval<Args&>())...))
INVOKE(F&& f, Args&&... args) { ... }
例如,其他的都一样。这可以简化,但即使您简化了它,return 类型不能使用与 return
表达式相同的语法这一事实也很难理解发生了什么。因此有了新的语法。
SFINAE 唯一不起作用的情况是推导的 return 类型。他们也使用 auto
,但禁用 SFINAE 的并不是 auto
关键字本身。