Apache Mesos
result_of.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_RESULT_OF_HPP__
14 #define __STOUT_RESULT_OF_HPP__
15 
16 #include <type_traits>
17 
18 #ifndef __WINDOWS__
19 using std::result_of;
20 #else
21 // TODO(mpark): Switch back to simply using `std::result_of` this once we
22 // upgrade our Windows support to VS 2015 Update 2 (MESOS-3993).
23 
24 #include <utility>
25 
26 namespace internal {
27 
28 // TODO(mpark): Consider pulling this out to something like <stout/meta.hpp>,
29 // This pattern already exists in `<process/future.hpp>`.
30 struct LessPrefer {};
31 struct Prefer : LessPrefer {};
32 
33 
34 // A tag type that indicates substitution failure.
35 struct Fail;
36 
37 // Perform the necessary expression SFINAE in a context supported in VS 2015
38 // Update 1. Note that it leverages `std::invoke` which is carefully written to
39 // avoid the limitations around the partial expression SFINAE support.
40 
41 // `std::invoke` is a C++17 feature, but we only compile this code for Windows,
42 // which has it implemented in VS 2015 Update 1. It is also supposed to be
43 // defined in `<functional>`, but is included in `<utility>` in VS.
44 template <typename F, typename... Args>
45 auto result_of_test(Prefer)
46  -> decltype(std::invoke(std::declval<F>(), std::declval<Args>()...));
47 
48 
49 // Report `Fail` if expression SFINAE fails in the above overload.
50 template <typename, typename...>
51 Fail result_of_test(LessPrefer);
52 
53 
54 // The generic case where `std::invoke(f, args...)` is well-formed.
55 template <typename T>
56 struct result_of_impl { using type = T; };
57 
58 
59 // The specialization for SFINAE failure case where
60 // `std::invoke(f, args...)` is ill-formed.
61 template <>
62 struct result_of_impl<Fail> {};
63 
64 
65 template <typename F>
66 struct result_of; // undefined.
67 
68 
69 // `decltype(result_of_test<F, Args...>(Prefer()))` is either `Fail` in the case
70 // of substitution failure, or the return type of `std::invoke(f, args...)`.
71 // `result_of_impl` provides a member typedef `type = T` only if `T != Fail`.
72 template <typename F, typename... Args>
73 struct result_of<F(Args...)>
74  : result_of_impl<decltype(result_of_test<F, Args...>(Prefer()))> {};
75 
76 } // namespace internal {
77 
78 using internal::result_of;
79 
80 #endif // __WINDOWS__
81 
82 #endif // __STOUT_RESULT_OF_HPP__
Try< uint32_t > type(const std::string &path)