25 #ifndef INCLUDED_ComVariant_h_GUID_A0A043D9_A146_4693_D351_06F6A04ABADA 26 #define INCLUDED_ComVariant_h_GUID_A0A043D9_A146_4693_D351_06F6A04ABADA 40 #include <type_traits> 49 using is_variant_type =
50 std::integral_constant<bool,
51 std::is_same<T, VARIANT>::value ||
52 std::is_same<T, VARIANTARG>::value>;
56 template <
typename T,
typename Result =
void *>
57 using enable_for_variants_t =
58 typename std::enable_if<is_variant_type<T>::value, Result>::type;
60 template <
typename OutputType>
struct VariantTypeTraits;
64 #if 0 // I don't actually see any members in the union to hold these... 65 template <>
struct VariantTypeTraits<const wchar_t *> {
66 static const auto vt = VT_LPWSTR;
68 template <>
struct VariantTypeTraits<const char *> {
69 static const auto vt = VT_LPSTR;
73 template <>
struct VariantTypeTraits<BSTR> {
74 static const auto vt = VT_BSTR;
75 template <
typename T>
static BSTR
get(
T &v) {
return v.bstrVal; }
80 struct VariantTypeTraits<
std::wstring> : VariantTypeTraits<BSTR> {
81 template <
typename T>
static std::wstring
get(
T &v) {
83 return std::wstring(static_cast<const wchar_t *>(bs),
87 template <
typename Dest>
struct VariantArrayTypeTraits {};
88 template <>
struct VariantArrayTypeTraits<BSTR> {
89 static const auto vt = VT_BSTR;
93 struct VariantArrayTypeTraits<
std::wstring>
94 : VariantArrayTypeTraits<BSTR> {
95 static std::wstring
get(SAFEARRAY &arr, std::size_t i) {
97 auto idx =
static_cast<long>(i);
100 SafeArrayGetElement(&arr, &idx, static_cast<void *>(&bs));
101 if (SUCCEEDED(hr) && bs) {
102 ret = std::wstring(static_cast<const wchar_t *>(bs),
112 namespace DestructionPolicies {
114 struct SilentAndAssert {
115 static void handle(HRESULT hr) {
119 case DISP_E_ARRAYISLOCKED:
126 case DISP_E_BADVARTYPE:
134 assert(hr != E_INVALIDARG &&
136 "VariantClear failed on variant " 137 "destruction: invalid " 146 struct DebugStringAndAssert {
147 static void handle(HRESULT hr) {
151 case DISP_E_ARRAYISLOCKED:
152 OutputDebugStringA(
"VariantClear failed on variant " 153 "destruction: Variant " 154 "contains an array that is locked");
156 case DISP_E_BADVARTYPE:
157 OutputDebugStringA(
"VariantClear failed on variant " 158 "destruction: Variant is " 162 assert(hr != E_INVALIDARG &&
164 "VariantClear failed on variant " 165 "destruction: invalid " 174 struct ThrowAndAssert {
175 static void handle(HRESULT hr) {
179 case DISP_E_ARRAYISLOCKED:
180 throw std::runtime_error(
181 "VariantClear failed on variant " 182 "destruction: Variant " 183 "contains an array that is locked");
185 case DISP_E_BADVARTYPE:
186 throw std::runtime_error(
187 "VariantClear failed on variant " 188 "destruction: Variant is " 192 assert(hr != E_INVALIDARG &&
194 "VariantClear failed on variant " 195 "destruction: invalid " 202 using Default = SilentAndAssert;
209 template <
typename T = VARIANT,
210 typename DestructionPolicy = DestructionPolicies::Default>
211 struct VariantHolder {
214 is_variant_type<T>::value,
215 "Only valid type parameters are VARIANT or VARIANTARG");
216 using type = VariantHolder<T>;
217 using unique_type = std::unique_ptr<type>;
218 static unique_type make_unique() {
219 unique_type ret(
new type);
222 VariantHolder() { VariantInit(getPtr()); }
224 auto hr = VariantClear(getPtr());
225 DestructionPolicy::handle(hr);
228 VariantHolder(VariantHolder
const &) =
delete;
230 VariantHolder &operator=(VariantHolder
const &) =
delete;
231 T &
get() {
return data_; }
232 T const &
get()
const {
return data_; }
233 T *getPtr() {
return &data_; }
234 T const *getPtr()
const {
return &data_; }
242 template <
typename Dest>
struct VariantSafeArrayRange {
244 explicit VariantSafeArrayRange(SAFEARRAY &arr) : arr_(arr) {
245 if (SafeArrayGetDim(&arr_) != numDims_) {
247 throw std::runtime_error(
248 "Can't use this class on this array: " 249 "we assume a 1-dimensional array, " 250 "which this is not!");
252 if (!SUCCEEDED(SafeArrayGetUBound(&arr_, dim_, &uBound_))) {
253 throw std::runtime_error(
254 "Couldn't get 0th dimension upper bound.");
257 if (!SUCCEEDED(SafeArrayGetLBound(&arr_, dim_, &lBound_))) {
258 throw std::runtime_error(
259 "Couldn't get 0th dimension lower bound.");
262 using type = VariantSafeArrayRange<Dest>;
264 Dest
get(std::size_t i)
const {
265 return detail::VariantArrayTypeTraits<Dest>::get(arr_, i);
267 struct SafeArrayRangeIterator {
269 SafeArrayRangeIterator() {}
271 SafeArrayRangeIterator(type
const &range,
long idx)
272 : elt_(idx), range_(&range) {
276 explicit operator bool()
const {
return range_ !=
nullptr; }
278 bool operator==(SafeArrayRangeIterator
const &other)
const {
279 return (elt_ == other.elt_) && (range_ == other.range_);
281 bool operator!=(SafeArrayRangeIterator
const &other)
const {
282 return elt_ != other.elt_ || range_ != other.range_;
285 Dest
operator*()
const {
return range_->get(elt_); }
287 SafeArrayRangeIterator &operator++() {
291 SafeArrayRangeIterator &operator++(
int) {
292 SafeArrayRangeIterator copy(*
this);
306 if (!range_->inBounds(elt_)) {
311 elt_ = INVALID_ELEMENT;
314 static const long INVALID_ELEMENT = -1;
315 long elt_ = INVALID_ELEMENT;
316 type
const *range_ =
nullptr;
318 bool inBounds(
long idx)
const {
319 return idx >= lBound_ && idx <= uBound_;
322 using iterator = SafeArrayRangeIterator;
323 using const_iterator = SafeArrayRangeIterator;
324 SafeArrayRangeIterator begin()
const {
325 return SafeArrayRangeIterator(*
this, lBound_);
327 SafeArrayRangeIterator end()
const {
328 return SafeArrayRangeIterator();
333 const UINT numDims_ = 1;
343 template <
typename T = VARIANT,
344 typename DestructionPolicy = detail::DestructionPolicies::Default>
345 class VariantWrapper {
348 static_assert(detail::is_variant_type<T>::value,
349 "Only valid type parameters are VARIANT or VARIANTARG");
350 using variant_type =
T;
351 using destruction_policy = DestructionPolicy;
352 using type = VariantWrapper<T, DestructionPolicy>;
353 using holder_type = detail::VariantHolder<T, DestructionPolicy>;
354 using holder_unique_ptr =
typename holder_type::unique_type;
357 VariantWrapper() : data_(holder_type::make_unique()) {}
360 explicit VariantWrapper(std::nullptr_t) {}
364 VariantWrapper(VariantWrapper
const &other) : VariantWrapper() {
366 throw std::logic_error(
367 "On variant copy-construction: tried to " 368 "copy from a variant in an invalid state " 376 VariantWrapper(VariantWrapper &&other)
377 : data_(
std::move(other.data_)) {}
381 type &operator=(type &&other) {
383 data_ = std::move(other.data_);
389 type &operator=(VariantWrapper
const &other) {
391 throw std::logic_error(
392 "On variant copy-assignment: tried to copy " 393 "from a variant in an invalid state " 397 auto hr = VariantCopy(getPtr(), other.getPtr());
401 case DISP_E_ARRAYISLOCKED:
402 throw std::runtime_error(
403 "VariantCopy failed on variant " 404 "copy-construction/assignment: Variant " 405 "contains an array that is locked");
407 case DISP_E_BADVARTYPE:
408 throw std::runtime_error(
409 "VariantCopy failed on variant " 410 "copy-construction/assignment: Variant is " 414 throw std::invalid_argument(
415 "VariantCopy failed on variant " 416 "copy-construction/assignment: invalid " 420 throw std::runtime_error(
"VariantCopy failed on variant " 421 "copy-construction/assignment: " 422 "insufficient memory.");
430 explicit operator bool()
const {
return bool(data_); }
435 data_ = holder_type::make_unique();
441 void dealloc() { data_.reset(); }
445 variant_type &
get() {
return data_->get(); }
446 variant_type
const &
get()
const {
return data_->get(); }
447 variant_type *getPtr() {
return data_->getPtr(); }
448 variant_type
const *getPtr()
const {
return data_->getPtr(); }
452 holder_unique_ptr data_;
456 template <
typename T>
inline T *AttachVariant(VariantWrapper<T> &v) {
460 using Variant = VariantWrapper<VARIANT>;
461 using VariantArg = VariantWrapper<VARIANTARG>;
465 template <
typename Dest,
typename T>
466 inline detail::enable_for_variants_t<T, bool>
contains(
T const &v) {
467 return (v.vt == detail::VariantTypeTraits<Dest>::vt);
471 template <
typename Dest,
typename T>
472 inline bool contains(VariantWrapper<T>
const &v) {
473 return v && contains<Dest>(v.get());
478 template <
typename Dest,
typename T>
479 inline detail::enable_for_variants_t<T, bool> containsArray(
T const &v) {
480 return (v.vt == (detail::VariantTypeTraits<Dest>::vt | VT_ARRAY));
484 template <
typename Dest,
typename T>
485 inline bool containsArray(VariantWrapper<T>
const &v) {
486 return v && containsArray<Dest>(v.get());
490 template <
typename T>
491 inline detail::enable_for_variants_t<T, bool> is_empty(
T const &v) {
492 return (v.vt == VT_EMPTY);
497 template <
typename T>
inline bool is_empty(VariantWrapper<T>
const &v) {
498 return (!v) || is_empty(v.get());
503 template <
typename Dest,
typename T>
504 inline detail::enable_for_variants_t<T, Dest>
get(
T const &v) {
505 if (!contains<Dest>(v)) {
506 throw std::invalid_argument(
507 "Variant does not contain the type of data " 508 "you are trying to access!");
510 return detail::VariantTypeTraits<Dest>::get(v);
515 template <
typename Dest,
typename T>
516 inline Dest
get(VariantWrapper<T>
const &v) {
517 if (!contains<Dest>(v)) {
518 throw std::invalid_argument(
519 "Variant does not contain the type of data " 520 "you are trying to access!");
522 return get<Dest>(v.get());
526 template <
typename Dest,
typename T>
527 inline detail::enable_for_variants_t<T, Dest> getArray(
T const &v,
529 if (!containsArray<Dest>(v)) {
530 throw std::invalid_argument(
531 "Variant does not contain an array of the type of data " 532 "you are trying to access!");
534 SAFEARRAY *arr = V_ARRAY(&v);
535 return detail::VariantArrayTypeTraits<Dest>::get(*arr, i);
539 template <
typename Dest,
typename T>
540 inline Dest getArray(VariantWrapper<T>
const &v, std::size_t i) {
541 if (!containsArray<Dest>(v)) {
542 throw std::invalid_argument(
543 "Variant does not contain an array of the type of data " 544 "you are trying to access!");
546 return getArray<Dest>(v.get());
551 template <
typename Dest,
typename T>
552 inline detail::enable_for_variants_t<T, detail::VariantSafeArrayRange<Dest>>
553 getArray(
T const &v) {
554 if (!containsArray<Dest>(v)) {
555 throw std::invalid_argument(
556 "Variant does not contain an array of the type of data " 557 "you are trying to access!");
559 SAFEARRAY *arr = V_ARRAY(&v);
560 return detail::VariantSafeArrayRange<Dest>(*arr);
564 template <
typename Dest,
typename T>
565 inline detail::VariantSafeArrayRange<Dest>
566 getArray(VariantWrapper<T>
const &v) {
567 if (!containsArray<Dest>(v)) {
568 throw std::invalid_argument(
569 "Variant does not contain an array of the type of data " 570 "you are trying to access!");
572 return getArray<Dest>(v.get());
576 using namespace variant;
582 #endif // INCLUDED_ComVariant_h_GUID_A0A043D9_A146_4693_D351_06F6A04ABADA apply_list< quote< or_ >, transform< Haystack, detail::is_< Needle >>> contains
Determines if type Needle is in the list Haystack - is an alias for a type that inherits std::true_ty...
Definition: Contains.h:49
Definition: TypeSafeIdHash.h:44
const internal::permut_matrix_product_retval< PermutationDerived, Derived, OnTheRight > operator*(const MatrixBase< Derived > &matrix, const PermutationBase< PermutationDerived > &permutation)
Definition: PermutationMatrix.h:539
Definition: ComInit.cpp:34
Definition: newuoa.h:1888
A small structure to hold a non zero as a triplet (i,j,value).
Definition: SparseUtil.h:148