-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
scalar_conversion_traits.h
107 lines (99 loc) · 3.51 KB
/
scalar_conversion_traits.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#pragma once
#include <type_traits>
#include "drake/common/symbolic/expression.h"
namespace drake {
namespace systems {
namespace scalar_conversion {
/// A templated traits class for whether an `S<U>` can be converted into an
/// `S<T>`; the default value is true for all values of `S`, `T`, and `U`.
/// Particular scalar-dependent classes (`S`) may specialize this template to
/// indicate whether the framework should support conversion for any given
/// combination of `T` and `U`.
///
/// When `Traits<S>::supported<T, U>` is `std::true_type`, the
/// "scalar-converting copy constructor" that relates `S`, `T`, and `U` will be
/// used. That constructor takes the form of, e.g., when `S` is `Foo`:
///
/// @code
/// template <typename T>
/// class Foo {
/// template <typename U>
/// explicit Foo(const Foo<U>& other);
/// };
/// @endcode
///
/// See @ref system_scalar_conversion for detailed background and examples
/// related to scalar-type conversion support.
///
/// When `Traits<S>::supported<T, U>` is `std::false_type`, the
/// `S<T>::S(const S<U>&)` scalar-conversion copy constructor will not even be
/// mentioned by the framework, so that `S` need not even compile for certain
/// values of `T` and `U`.
///
/// @tparam S is the scalar-templated type to copy
template <template <typename> class S>
struct Traits {
/// @tparam T is the resulting scalar type (to convert into)
/// @tparam U is the donor scalar type (to convert from)
template <typename T, typename U>
using supported = std::true_type;
};
/// A concrete traits class providing sugar to disable support for symbolic
/// evaluation (i.e., the symbolic::Expression scalar type).
///
/// For example, if MySystem does not support the symbolic expression scalar
/// type, it could specialize Traits as follows:
///
/// @code
/// namespace drake {
/// namespace systems {
/// namespace scalar_conversion {
/// template <> struct Traits<MySystem> : public NonSymbolicTraits {};
/// } // namespace scalar_conversion
/// } // namespace systems
/// } // namespace drake
/// @endcode
struct NonSymbolicTraits {
template <typename T, typename U>
using supported = typename std::bool_constant<
!std::is_same_v<T, symbolic::Expression> &&
!std::is_same_v<U, symbolic::Expression>>;
};
/// A concrete traits class providing sugar to support for converting only from
/// the `double` scalar type. For example, if a MySystem<symbolic::Expression>
/// cannot be converted into a MySystem<double>, it could specialize Traits as
/// follows:
///
/// @code
/// namespace drake {
/// namespace systems {
/// namespace scalar_conversion {
/// template <> struct Traits<MySystem> : public FromDoubleTraits {};
/// } // namespace scalar_conversion
/// } // namespace systems
/// } // namespace drake
/// @endcode
struct FromDoubleTraits {
template <typename T, typename U>
using supported = typename std::bool_constant<std::is_same_v<U, double>>;
};
/// Converts a scalar `U u` to its corresponding scalar `T t`. When U == T,
/// the scalar is unchanged. When demoting Expression to non-Expression,
/// throws when there are unbound variables. In all other cases, information
/// beyond the double value (e.g., possible derivatives) might be discarded.
template <typename T, typename U>
struct ValueConverter {
T operator()(const U& u) const {
return ExtractDoubleOrThrow(u);
}
};
template <typename T>
struct ValueConverter<T, T> {
using U = T;
T operator()(const U& u) const {
return u;
}
};
} // namespace scalar_conversion
} // namespace systems
} // namespace drake