Caffe2 - C++ API
A deep learning, cross platform ML framework
pimpl-inl.h
1 // This class exists only to do SFINAE on abstract types `T` that are really
2 // `ModuleHolder<ModuleType>`, because there's no good way to say that `T` is a
3 // `ModuleHolder` over some unknown type `ModuleType`. With this, you can do
4 // `enable_if_t<is_base_of_v<ModuleHolderIndicator, T>>`.
6 
7 // A type trait that is true for types that are `ModuleHolder`s.
8 template <typename T>
9 using is_module_holder = std::is_base_of<ModuleHolderIndicator, decay_t<T>>;
10 
11 template <typename T>
12 using disable_if_module_holder_t = disable_if_t<is_module_holder<T>::value>;
13 
14 // A collection of templates that answer the question whether a type `T` is a
15 // `ModuleHolder`, and if so whether its contained type is of type `C`. This is
16 // tricky because it is hard to short circuit in template metaprogramming. A
17 // naive and incorrect solution to this problem would be something like
18 // `disable_if<is_module_holder<T>::value && typename T::ContainedType == C>`.
19 // This would disable all types that are not `ModuleHolder`s, because even
20 // though the `is_module_holder<T>::value` may be `false` for such types the
21 // `T::ContainedType` access would be ill-formed and thus fail the whole
22 // expression by the rules of SFINAE. Instead we have to use template
23 // specialization to statically branch on the first condition
24 // (`is_module_holder<T>`) and are only then allowed to query
25 // `T::ContainedType` in the branch for which the condition was true.
26 
27 // Base template.
28 template <bool is_module_holder_value, typename T, typename C>
30 
31 // False branch. `T` is not a `ModuleHolder` and thus not a `ModuleHolder` with
32 // contained type `C`.
33 template <typename T, typename C>
34 struct is_module_holder_of_impl<false, T, C> : std::false_type {};
35 
36 // True branch. `T` is a `ModuleHolder` and thus we can legit access its
37 // `ContainedType` and compare it against `C`.
38 template <typename T, typename C>
39 struct is_module_holder_of_impl<true, T, C>
40  : std::is_same<typename T::ContainedType, C> {};
41 
42 // Helper template.
43 template <typename T, typename C>
45  is_module_holder<T>::value,
46  decay_t<T>,
47  decay_t<C>> {};
48 
49 // A collection of templates that allow deducing the return type of the
50 // `forward()` method, but only if a module actually has a `forward()` method,
51 // and otherwise deduces to the type `void`.
52 
53 template <bool has_forward_value, typename C, typename... Args>
55 
56 template <typename C, typename... Args>
57 struct return_type_of_forward_impl<true, C, Args...> {
58  using type = decltype(::std::declval<C>().forward(::std::declval<Args>()...));
59 };
60 
61 template <typename C, typename... Args>
62 struct return_type_of_forward_impl<false, C, Args...> {
63  using type = void;
64 };
65 
66 template <typename C, typename... Args>
69  C,
70  Args...>;
71 
72 template <typename C, typename... Args>
73 using return_type_of_forward_t =
74  typename return_type_of_forward<C, Args...>::type;
Detects if a type T has a forward() method.
Definition: static.h:19
Definition: static.cpp:64