Last active
December 15, 2015 10:12
-
-
Save mpark/1952afb0017209cb8599 to your computer and use it in GitHub Desktop.
C++14 `result_of` in VS 2015 Update 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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