@@ -157,64 +157,83 @@ namespace adm {
157157 }
158158 };
159159
160+ // / base class which has methods for each type in a variant parameter.
161+ // /
162+ // / This should be used in HasParameters, with Parameter being a
163+ // / parameter like OptionalParameter<V>, where V is a boost::variant.
164+ // /
165+ // / When using this with OptionalParameter<V>, the following classes should
166+ // / be explicitly instantiated:
167+ // / - OptionalParameter<V>
168+ // / - One VariantTypeParameter<OptionalParameter<V>, T> for each T in V.
169+ // / - VariantParameter<OptionalParameter<V>>
170+ template <typename Parameter,
171+ typename Variant = typename Parameter::ParameterType>
172+ class VariantParameter ;
173+
160174 // / Base class for one type within a variant.
161175 // /
162- // / VariantParam should be a parameter type like
176+ // / Parameter should be a parameter type like
163177 // / OptionalParameter<boost::variant<...>>, and T should be one of the
164178 // / types of the variant.
165- template <typename VariantParam, typename T>
166- class VariantTypeParameter : public virtual VariantParam {
167- using Variant = typename VariantParam::ParameterType;
179+ // /
180+ // / this uses CRTP with VariantParameter to access the Variant type
181+ template <typename Parameter, typename T>
182+ class VariantTypeParameter {
183+ using Base = VariantParameter<Parameter>;
168184 using Tag = typename detail::ParameterTraits<T>::tag;
169- using VariantTag = typename detail::ParameterTraits<Variant>::tag;
185+
186+ Base& base () { return static_cast <Base&>(*this ); }
187+
188+ const Base& base () const { return static_cast <const Base&>(*this ); }
170189
171190 public:
172- using VariantParam::get;
173191 ADM_BASE_EXPORT T get (Tag) const {
174- return boost::get<T>(get (VariantTag{}));
192+ return boost::get<T>(base (). get (typename Base:: VariantTag{}));
175193 }
176194
177- using VariantParam::set;
178195 ADM_BASE_EXPORT void set (T value) {
179- return VariantParam:: set (std::move (value));
196+ return base (). set (typename Base::Variant{ std::move (value)} );
180197 }
181198
182- using VariantParam::has;
183199 ADM_BASE_EXPORT bool has (Tag) const {
184- return has (VariantTag{}) && get (VariantTag ()).type () == typeid (T);
200+ return base ().has (typename Base::VariantTag{}) &&
201+ base ().get (typename Base::VariantTag{}).type () == typeid (T);
185202 }
186203
187- using VariantParam::isDefault;
188204 ADM_BASE_EXPORT bool isDefault (Tag) const {
189- return isDefault (VariantTag ()) && get (VariantTag ()).type () == typeid (T);
205+ return base ().isDefault (typename Base::VariantTag{}) &&
206+ base ().get (typename Base::VariantTag{}).type () == typeid (T);
190207 }
191208
192- using VariantParam::unset;
193209 ADM_BASE_EXPORT void unset (Tag) {
194- if (has (Tag{})) unset (VariantTag{});
210+ if (has (Tag{})) base (). unset (typename Base:: VariantTag{});
195211 }
196212 };
197213
198- template <typename VariantParam, typename VariantParameter>
199- struct VariantParameterHelper ;
214+ // implementation of VariantParameter; see above
215+ template <typename Parameter, typename ... Options>
216+ class VariantParameter <Parameter, boost::variant<Options...>>
217+ : public Parameter, public VariantTypeParameter<Parameter, Options>... {
218+ public:
219+ using Variant = boost::variant<Options...>;
220+ using VariantTag = typename detail::ParameterTraits<Variant>::tag;
221+
222+ using Parameter::get;
223+ using VariantTypeParameter<Parameter, Options>::get...;
200224
201- template <typename VariantParam, typename ... Ts>
202- struct VariantParameterHelper <VariantParam, boost::variant<Ts...>> {
203- using type = HasParameters<VariantTypeParameter<VariantParam, Ts>...>;
204- };
225+ using Parameter::set;
226+ using VariantTypeParameter<Parameter, Options>::set...;
205227
206- // / Wrapper which has methods for each type in a variant parameter.
207- // /
208- // / This should be used in HasParameters, with VariantParam being a
209- // / parameter like OptionalParameter<V>, where V is a boost::variant.
210- // /
211- // / When using this with OptionalParameter<V>, the following classes should
212- // / be explicitly instantiated:
213- // / - OptionalParameter<V> (not VariantParameter<...>)
214- // / - One VariantTypeParameter<OptionalParameter<V>, T> for each T in V.
215- template <typename VariantParam>
216- using VariantParameter = typename VariantParameterHelper<
217- VariantParam, typename VariantParam::ParameterType>::type;
228+ using Parameter::has;
229+ using VariantTypeParameter<Parameter, Options>::has...;
230+
231+ using Parameter::isDefault;
232+ using VariantTypeParameter<Parameter, Options>::isDefault...;
233+
234+ using Parameter::unset;
235+ using VariantTypeParameter<Parameter, Options>::unset...;
236+ };
218237
219238 // / Helper containing templated wrapper methods like `has<Param>()` around
220239 // / overloaded `has(ParamTag)` type methods defined in T.
0 commit comments