Skip to content

Commit 3642d45

Browse files
committed
auto_base: avoid virtual inheritance for variants
1 parent 46cff25 commit 3642d45

File tree

1 file changed

+52
-33
lines changed

1 file changed

+52
-33
lines changed

include/adm/detail/auto_base.hpp

+52-33
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)