Tested on Linux-x64. 2017-01-09 Ville Voutilainen <ville.voutilai...@gmail.com>
Reduce the size of variant, it doesn't need an index of type size_t internally. * include/std/variant (parse_numbers.h): New include. (__select_index): New. (_Variant_storage<false, _Types...>::_M_reset_impl): Use _index_type for comparison with variant_npos. (_Variant_storage<false, _Types...>::__index_type): New. (_Variant_storage<false, _Types...>::_M_index): Change the type from size_t to __index_type. (_Variant_storage<true, _Types...>::__index_type): New. (_Variant_storage<true, _Types...>::_M_index): Change the type from size_t to __index_type. (_Variant_base::_M_valid): Use __index_type for comparison with variant_npos. (variant::__index_type): New. (variant::index): Use __index_type for comparison with variant_npos. * testsuite/20_util/variant/index_type.cc: New.
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 3d025a7..b016f32 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -43,6 +43,7 @@ #include <bits/functional_hash.h> #include <bits/invoke.h> #include <ext/aligned_buffer.h> +#include <bits/parse_numbers.h> namespace std _GLIBCXX_VISIBILITY(default) { @@ -314,6 +315,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<bool __trivially_destructible, typename... _Types> struct _Variant_storage; + template <typename... _Types> + using __select_index = + typename __select_int::_Select_int_base<sizeof...(_Types)+1, + unsigned char, + unsigned short> + ::type::value_type; + template<typename... _Types> struct _Variant_storage<false, _Types...> { @@ -332,7 +340,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<size_t... __indices> constexpr void _M_reset_impl(std::index_sequence<__indices...>) { - if (_M_index != variant_npos) + if (_M_index != __index_type(variant_npos)) _S_vtable<__indices...>[_M_index](*this); } @@ -346,7 +354,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _M_reset(); } _Variadic_union<_Types...> _M_u; - size_t _M_index; + using __index_type = __select_index<_Types...>; + __index_type _M_index; }; template<typename... _Types> @@ -364,7 +373,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _M_index = variant_npos; } _Variadic_union<_Types...> _M_u; - size_t _M_index; + using __index_type = __select_index<_Types...>; + __index_type _M_index; }; // Helps SFINAE on special member functions. Otherwise it can live in variant @@ -487,7 +497,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr bool _M_valid() const noexcept - { return this->_M_index != variant_npos; } + { + return this->_M_index != + typename _Storage::__index_type(variant_npos); + } }; // For how many times does _Tp appear in _Tuple? @@ -944,6 +957,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __detail::__variant::__index_of_v<_Tp, _Types...>; public: + using __index_type = typename _Base::_Storage::__index_type; constexpr variant() noexcept(is_nothrow_default_constructible_v<__to_type<0>>) = default; variant(const variant&) = default; @@ -1086,7 +1100,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !this->_M_valid(); } constexpr size_t index() const noexcept - { return this->_M_index; } + { + if (this->_M_index == __index_type(variant_npos)) + return variant_npos; + return this->_M_index; + } void swap(variant& __rhs) diff --git a/libstdc++-v3/testsuite/20_util/variant/index_type.cc b/libstdc++-v3/testsuite/20_util/variant/index_type.cc new file mode 100644 index 0000000..ea6b4d6 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/variant/index_type.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <variant> +#include <type_traits> +#include <climits> + +template <size_t N> struct Bogus {}; + +template <size_t... I> auto f(std::index_sequence<I...>) +{ + return std::variant<Bogus<I>...>{}; +} + +static_assert(sizeof(char) >= sizeof(int) || + CHAR_BIT != 8 || + std::is_same_v< + decltype(f(std::make_index_sequence<3>()))::__index_type, + unsigned char>); + +static_assert(sizeof(char) >= sizeof(int) || + sizeof(char) >= sizeof(short) || + CHAR_BIT != 8 || + std::is_same_v< + decltype(f(std::make_index_sequence<260>()))::__index_type, + unsigned short>);