Bug 1246841 - Allow construction of Variant values using type inference. r=waldo

--HG--
extra : rebase_source : 7d596149e6d3c630d62aab0d65d5a826af731bf5
This commit is contained in:
Seth Fowler 2016-02-25 14:34:12 -08:00
Родитель 4052eca615
Коммит 27ae3900e1
1 изменённых файлов: 87 добавлений и 0 удалений

Просмотреть файл

@ -247,6 +247,39 @@ struct VariantImplementation<N, T, Ts...>
}
};
/**
* AsVariantTemporary stores a value of type T to allow construction of a
* Variant value via type inference. Because T is copied and there's no
* guarantee that the copy can be elided, AsVariantTemporary is best used with
* primitive or very small types.
*/
template <typename T>
struct AsVariantTemporary
{
explicit AsVariantTemporary(const T& aValue)
: mValue(aValue)
{}
template<typename U>
explicit AsVariantTemporary(U&& aValue)
: mValue(Forward<U>(aValue))
{}
AsVariantTemporary(const AsVariantTemporary& aOther)
: mValue(aOther.mValue)
{}
AsVariantTemporary(AsVariantTemporary&& aOther)
: mValue(Move(aOther.mValue))
{}
AsVariantTemporary() = delete;
void operator=(const AsVariantTemporary&) = delete;
void operator=(AsVariantTemporary&&) = delete;
typename RemoveConst<typename RemoveReference<T>::Type>::Type mValue;
};
} // namespace detail
/**
@ -270,6 +303,18 @@ struct VariantImplementation<N, T, Ts...>
* Variant<char, uint32_t> v1('a');
* Variant<UniquePtr<A>, B, C> v2(MakeUnique<A>());
*
* Because specifying the full type of a Variant value is often verbose,
* AsVariant() can be used to construct a Variant value using type inference in
* contexts such as expressions or when returning values from functions. Because
* AsVariant() must copy or move the value into a temporary and this cannot
* necessarily be elided by the compiler, it's mostly appropriate only for use
* with primitive or very small types.
*
*
* Variant<char, uint32_t> Foo() { return AsVariant('x'); }
* // ...
* Variant<char, uint32_t> v1 = Foo(); // v1 holds char('x').
*
* All access to the contained value goes through type-safe accessors.
*
* void
@ -391,6 +436,19 @@ public:
new (ptr()) T(Forward<T>(aT));
}
/**
* Constructs this Variant from an AsVariantTemporary<T> such that T can be
* stored in one of the types allowable in this Variant. This is used in the
* implementation of AsVariant().
*/
template<typename RefT,
typename T = typename detail::SelectVariantType<RefT, Ts...>::Type>
MOZ_IMPLICIT Variant(detail::AsVariantTemporary<RefT>&& aValue)
: tag(Impl::template tag<T>())
{
new (ptr()) T(Move(aValue.mValue));
}
/** Copy construction. */
Variant(const Variant& aRhs)
: tag(aRhs.tag)
@ -421,6 +479,15 @@ public:
return *this;
}
/** Move assignment from AsVariant(). */
template <typename T>
Variant& operator=(detail::AsVariantTemporary<T>&& aValue)
{
this->~Variant();
new (this) Variant(Move(aValue));
return *this;
}
~Variant()
{
Impl::destroy(*this);
@ -502,6 +569,26 @@ public:
}
};
/*
* AsVariant() is used to construct a Variant<T,...> value containing the
* provided T value using type inference. It can be used to construct Variant
* values in expressions or return them from functions without specifying the
* entire Variant type.
*
* Because AsVariant() must copy or move the value into a temporary and this
* cannot necessarily be elided by the compiler, it's mostly appropriate only
* for use with primitive or very small types.
*
* AsVariant() returns a AsVariantTemporary value which is implicitly
* convertible to any Variant that can hold a value of type T.
*/
template<typename T>
detail::AsVariantTemporary<T>
AsVariant(T&& aValue)
{
return detail::AsVariantTemporary<T>(Forward<T>(aValue));
}
} // namespace mozilla
#endif /* mozilla_Variant_h */