HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
strongparam.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio
4 
5 
6 #pragma once
7 
8 #include <type_traits>
9 
11 
13 
14 
15 /// StrongParam is used to construct an implementation of a derived type
16 /// that lets you pass strongly typed parameters. It implicitly converts TO
17 /// the basetype, but requires explicit conversion FROM the basetype.
18 ///
19 /// The problem this is meant to address is that you may have a function
20 /// that has multiple bool, int, or float paramters, particularly if they
21 /// are adjacent in the call signature. This is extremely error prone. For
22 /// example, suppose you have
23 ///
24 /// void func (bool verbose, bool crazy, int apples, int oranges);
25 ///
26 /// and then it is called:
27 ///
28 /// func(true, false, 3, 8);
29 ///
30 /// Is this correct, or does it harbor a bug? Your guess is as good as mine.
31 /// In comparison, Python has a syntax that lets you name parameters, which
32 /// looks like this:
33 ///
34 /// func(verbose=true, crazy=false, apples=3, oranges=8);
35 ///
36 /// But, unfortunately, no such syntax exists in C++. Maybe someday it will,
37 /// but for now, we want something we can use to make the function call
38 /// similarly clear. Like this:
39 ///
40 /// func(Verbose(true), Crazy(false), Apples(3), Oranges(8));
41 ///
42 /// and simultaneously for the following to be considered errors:
43 ///
44 /// // Not allowed: bare bools and ints
45 /// func(true, false, 3, 8);
46 ///
47 /// // Not allowed: getting the order wrong
48 /// func(Crazy(false), Verbose(true), Oranges(8), Apples(3));
49 ///
50 /// Our solution is inspired by
51 /// https://lists.llvm.org/pipermail/llvm-dev/2019-August/134302.html
52 /// though we have simplified it quite a bit for our needs.
53 ///
54 /// Example use 1: Use StrongParam to disambiguate parameters.
55 ///
56 /// // Use macro to generate the new types
57 /// OIIO_STRONG_PARAM_TYPE(Verbose, bool);
58 /// OIIO_STRONG_PARAM_TYPE(Crazy, bool);
59 ///
60 /// bool
61 /// compute (Verbose a, Crazy b)
62 /// {
63 /// return a | b;
64 /// }
65 ///
66 ///
67 /// Example 2: Use StrongParam to disambiguate two floats, a poor person's
68 /// implementation of units:
69 ///
70 /// Error prone: speed(float,float) // which is first, meters or seconds?
71 /// Unambiguous: speed(Meters,Seconds)
72 ///
73 /// OIIO_STRONG_PARAM_TYPE(Meters, float);
74 /// OIIO_STRONG_PARAM_TYPE(Seconds, float);
75 ///
76 /// float
77 /// speed (Meters a, Seconds b)
78 /// {
79 /// return a / b;
80 /// }
81 ///
82 /// Note that the fancy strong type is for declaration purposes. Any time
83 /// you use it in the function, it implicitly converts to the underlying
84 /// base type.
85 ///
86 /// As an alternative to `OIIO_STRONG_TYPE(Meters, float)`, you may also use
87 /// this notation (if you find it more pleasing):
88 ///
89 /// using Meters = StrongParam<struct MetersTag, float>;
90 ///
91 /// The MetersTag struct need not be defined anywhere, it just needs to
92 /// be a unique name.
93 ///
94 
95 template<typename Tag, typename Basetype> struct StrongParam {
96  // Construct a StrongParam from a Basetype.
97  explicit StrongParam(const Basetype& val)
98  : m_val(val)
99  {
100  }
101 
102  // Allow default simple copy construction
103  StrongParam(const StrongParam<Tag, Basetype>& val) = default;
104 
105  // Allow implicit conversion back to Basetype.
106  operator const Basetype&() const noexcept { return m_val; }
107 
108 private:
109  Basetype m_val;
110  static_assert(std::is_trivial<Basetype>::value, "Need trivial type");
111 };
112 
113 
114 
115 /// Convenience macro for making strong parameter type Name that is Basetype
116 /// underneath. What it actually does is make a new type that is derived
117 /// from StrongParam<Name,Basetype>.
118 #define OIIO_STRONG_PARAM_TYPE(Name, Basetype) \
119  struct Name : public StrongParam<Name, Basetype> { \
120  using StrongParam::StrongParam; \
121  }
122 
123 
GLsizei const GLfloat * value
Definition: glcorearb.h:824
GLuint GLfloat * val
Definition: glcorearb.h:1608
StrongParam(const Basetype &val)
Definition: strongparam.h:97
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93