Skip to content

Commit

Permalink
Merge pull request #162 from mapbox/variant_alternative
Browse files Browse the repository at this point in the history
add `variant_alternative` and `variant_size` implementations
  • Loading branch information
artemp authored Oct 23, 2017
2 parents ba3085a + 835ebc1 commit 237f83c
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ out/%.o: test/t/%.cpp Makefile $(ALL_HEADERS)
mkdir -p ./out
$(CXX) -c -o $@ $< -Iinclude -isystem test/include $(FINAL_CXXFLAGS)

out/unit: out/unit.o out/binary_visitor_1.o out/binary_visitor_2.o out/binary_visitor_3.o out/binary_visitor_4.o out/binary_visitor_5.o out/binary_visitor_6.o out/issue21.o out/issue122.o out/mutating_visitor.o out/optional.o out/recursive_wrapper.o out/sizeof.o out/unary_visitor.o out/variant.o
out/unit: out/unit.o out/binary_visitor_1.o out/binary_visitor_2.o out/binary_visitor_3.o out/binary_visitor_4.o out/binary_visitor_5.o out/binary_visitor_6.o out/issue21.o out/issue122.o out/mutating_visitor.o out/optional.o out/recursive_wrapper.o out/sizeof.o out/unary_visitor.o out/variant.o out/variant_alternative.o
mkdir -p ./out
$(CXX) -o $@ $^ $(LDFLAGS)

Expand Down
75 changes: 74 additions & 1 deletion include/mapbox/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ class variant

VARIANT_INLINE int which() const noexcept
{
return static_cast<int>(sizeof...(Types)-type_index - 1);
return static_cast<int>(sizeof...(Types) - type_index - 1);
}

template <typename T, typename std::enable_if<
Expand Down Expand Up @@ -1023,6 +1023,78 @@ ResultType const& get_unchecked(T const& var)
{
return var.template get_unchecked<ResultType>();
}
// variant_size
template <typename T>
struct variant_size;

//variable templates is c++14
//template <typename T>
//constexpr std::size_t variant_size_v = variant_size<T>::value;

template <typename T>
struct variant_size<const T>
: variant_size<T> {};

template <typename T>
struct variant_size<volatile T>
: variant_size<T> {};

template <typename T>
struct variant_size<const volatile T>
: variant_size<T> {};

template <typename... Types>
struct variant_size<variant<Types...>>
: std::integral_constant<std::size_t, sizeof...(Types)> {};

// variant_alternative
template <std::size_t Index, typename T>
struct variant_alternative;

#if defined(__clang__)
#if __has_builtin(__type_pack_element)
#define has_type_pack_element
#endif
#endif

#if defined(has_type_pack_element)
template <std::size_t Index, typename ...Types>
struct variant_alternative<Index, variant<Types...>>
{
static_assert(sizeof...(Types) > Index , "Index out of range");
using type = __type_pack_element<Index, Types...>;
};
#else
template <std::size_t Index, typename First, typename...Types>
struct variant_alternative<Index, variant<First, Types...>>
: variant_alternative<Index - 1, variant<Types...>>
{
static_assert(sizeof...(Types) > Index -1 , "Index out of range");
};

template <typename First, typename...Types>
struct variant_alternative<0, variant<First, Types...>>
{
using type = First;
};

#endif

template <size_t Index, typename T>
using variant_alternative_t = typename variant_alternative<Index, T>::type;

template <size_t Index, typename T>
struct variant_alternative<Index, const T>
: std::add_const<variant_alternative<Index, T>> {};

template <size_t Index, typename T>
struct variant_alternative<Index, volatile T>
: std::add_volatile<variant_alternative<Index, T>> {};

template <size_t Index, typename T>
struct variant_alternative<Index, const volatile T>
: std::add_cv<variant_alternative<Index, T>> {};

} // namespace util
} // namespace mapbox

Expand All @@ -1035,6 +1107,7 @@ struct hash< ::mapbox::util::variant<Types...>> {
return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v);
}
};

}

#endif // MAPBOX_UTIL_VARIANT_HPP
31 changes: 31 additions & 0 deletions test/t/variant_alternative.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "catch.hpp"

#include <mapbox/variant.hpp>
#include <mapbox/variant_io.hpp>

#include <string>

TEST_CASE("variant_alternative", "[types]")
{
using variant_type = mapbox::util::variant<int, double, std::string>;
using type_0 = mapbox::util::variant_alternative<0, variant_type>::type;
using type_1 = mapbox::util::variant_alternative<1, variant_type>::type;
using type_2 = mapbox::util::variant_alternative<2, variant_type>::type;
//using type_3 = mapbox::util::variant_alternative<3, variant_type>::type; // compile error
constexpr bool check_0 = std::is_same<int, type_0>::value;
constexpr bool check_1 = std::is_same<double, type_1>::value;
constexpr bool check_2 = std::is_same<std::string, type_2>::value;
CHECK(check_0);
CHECK(check_1);
CHECK(check_2);
}

TEST_CASE("variant_size", "[types]")
{
constexpr auto value_0 = mapbox::util::variant_size<mapbox::util::variant<>>::value;
constexpr auto value_1 = mapbox::util::variant_size<mapbox::util::variant<int>>::value;
constexpr auto value_2 = mapbox::util::variant_size<mapbox::util::variant<int, std::string>>::value;
CHECK(value_0 == 0);
CHECK(value_1 == 1);
CHECK(value_2 == 2);
}

0 comments on commit 237f83c

Please sign in to comment.