Skip to content

Instantly share code, notes, and snippets.

@mpark
Last active December 15, 2015 10:12
Show Gist options
  • Save mpark/1952afb0017209cb8599 to your computer and use it in GitHub Desktop.
Save mpark/1952afb0017209cb8599 to your computer and use it in GitHub Desktop.
C++14 `result_of` in VS 2015 Update 1
#include <type_traits>
namespace std {
namespace detail {
// A dummy tag type that indicates substitution failure. It should be hidden
// as best as possible, in this case it's just under the `detail` namespace.
struct fail;
// Perform the necessary expression SFINAE in a supported context.
// Note that it leverages `std::invoke` which is carefully written by STL to
// avoid the limitations around the partial expression SFINAE support.
template <typename, typename...>
fail result_of_type(...);
template <typename F, typename... Args>
auto result_of_type(int)
-> decltype(std::invoke(std::declval<F>(), std::declval<Args>()...));
// `decltype(result_of_type<F, Args...>(0))` is either `fail` in the case of
// substitution failure, or the return type of `invoke(f, args...)`.
// `result_of_impl` provides member typedef `type = R` if `R != fail`.
template <typename R>
using result_of_impl = std::enable_if<!std::is_same<R, fail>::value, R>;
template <typename>
struct result_of;
template <typename F, typename... Args>
struct result_of<F(Args...)>
: result_of_impl<decltype(result_of_type<F, Args...>(0))> {};
} // namespace detail
using detail::result_of;
} // namespace std
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment