Skip to content

Commit

Permalink
Merge pull request #144 from narizhny/Casts
Browse files Browse the repository at this point in the history
Add variant_static_cast, variant_dynamic_cast
  • Loading branch information
artemp authored Apr 25, 2017
2 parents 550ac2f + 51fccd7 commit 291121f
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,5 +166,5 @@ after_script:
make coverage;
./out/cov-test;
cp unit*gc* test/;
./.local/bin/cpp-coveralls --gcov /usr/bin/llvm-cov-3.5 --gcov-options '\-lp' -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp;
./.local/bin/cpp-coveralls --gcov /usr/bin/llvm-cov-3.5 --gcov-options '\-lp' -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp variant_cast.hpp;
fi
85 changes: 85 additions & 0 deletions include/mapbox/variant_cast.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#ifndef VARIANT_CAST_HPP
#define VARIANT_CAST_HPP

#include <type_traits>

namespace mapbox {
namespace util {

namespace detail {

template <class T>
class static_caster
{
public:
template <class V>
T& operator()(V& v) const
{
return static_cast<T&>(v);
}
};

template <class T>
class dynamic_caster
{
public:
using result_type = T&;
template <class V>
T& operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
{
throw std::bad_cast();
}
template <class V>
T& operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
{
return dynamic_cast<T&>(v);
}
};

template <class T>
class dynamic_caster<T*>
{
public:
using result_type = T*;
template <class V>
T* operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
{
return nullptr;
}
template <class V>
T* operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
{
return dynamic_cast<T*>(&v);
}
};
}

template <class T, class V>
typename detail::dynamic_caster<T>::result_type
dynamic_variant_cast(V& v)
{
return mapbox::util::apply_visitor(detail::dynamic_caster<T>(), v);
}

template <class T, class V>
typename detail::dynamic_caster<const T>::result_type
dynamic_variant_cast(const V& v)
{
return mapbox::util::apply_visitor(detail::dynamic_caster<const T>(), v);
}

template <class T, class V>
T& static_variant_cast(V& v)
{
return mapbox::util::apply_visitor(detail::static_caster<T>(), v);
}

template <class T, class V>
const T& static_variant_cast(const V& v)
{
return mapbox::util::apply_visitor(detail::static_caster<const T>(), v);
}
}
}

#endif // VARIANT_CAST_HPP

0 comments on commit 291121f

Please sign in to comment.