However, initial testing for boost::variant shows that that there is no
compile time check on the types allowed to instantiate boost::get on a
variant, example:
struct A {}; struct B {}; struct C{};
int main()
{
boost::variant v v;
boost::get<C>(v);
}
Compiles fine (gcc 4.1.1, boost 1.33.1) but errors at runtime throwing a
bad_get exception from get. It seems to me that the get<> on variant somehow
works for any type not checking if the type parameter for get matches one in
the type sequence of the given variant.
Maybe I miss something but shouldn't get on variant have a compile time type
check ? (this would catch at compile time common errors for variant use cases
I think)
I agree.
It might be true that the version without compile-time has its just
usages, but the version with the compile-time check is much more useful.
So I found myself adding the following functions:
template
void assert_variant_has_type(const Variant &)
{
BOOST_MPL_ASSERT((mpl::contains));
}
template
inline typename add_pointer<U>::type get_exact(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
{
assert_variant_has_type<U>(*operand);
typedef typename add_pointer<U>::type U_ptr;
if (!operand) return static_cast(0);
if (operand->type() != typeid(U)) return static_cast(0);
detail::variant::get_visitor<U> v;
return operand->apply_visitor(v);
}
template
inline typename add_pointer<const U>::type get_exact(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
{
assert_variant_has_type<U>(*operand);
typedef typename add_pointer<const U>::type U_ptr;
if (!operand) return static_cast(0);
if (operand->type() != typeid(U)) return static_cast(0);
detail::variant::get_visitor<const U> v;
return operand->apply_visitor(v);
}
template
inline typename add_reference<U>::type get_exact(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
{
typedef typename add_pointer<U>::type U_ptr;
U_ptr result = get_exact<U>(&operand);
if (!result)
throw bad_get();
return *result;
}
template
inline typename add_reference<const U>::type get_exact(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U))
{
typedef typename add_pointer<const U>::type U_ptr;
U_ptr result = get_exact<const U>(&operand);
if (!result)
throw bad_get();
return *result;
}