[v3 PATCH] PR libstdc++/87619

Jonathan Wakely jwakely@redhat.com
Wed Oct 17 09:07:00 GMT 2018


On 16/10/18 22:59 +0300, Ville Voutilainen wrote:
>Simple, short, and sweet, just a thinko.
>
>2018-10-16  Ville Voutilainen  <ville.voutilainen@gmail.com>
>
>    PR libstdc++/87619
>    * include/std/variant (__select_index): Fix an off-by-one.
>    * testsuite/20_util/variant/87619.cc: New.

>diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
>index 2d86a70..55b6440 100644
>--- a/libstdc++-v3/include/std/variant
>+++ b/libstdc++-v3/include/std/variant
>@@ -362,7 +362,7 @@ namespace __variant
> 
>   template <typename... _Types>
>   using __select_index =
>-    typename __select_int::_Select_int_base<sizeof...(_Types) + 1,
>+    typename __select_int::_Select_int_base<sizeof...(_Types),
> 					    unsigned char,
> 					    unsigned short>::type::value_type;
> 
>diff --git a/libstdc++-v3/testsuite/20_util/variant/87619.cc b/libstdc++-v3/testsuite/20_util/variant/87619.cc
>new file mode 100644
>index 0000000..a8db6b8
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/20_util/variant/87619.cc
>@@ -0,0 +1,46 @@
>+// Copyright (C) 2018 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/>.
>+
>+// { dg-options "-std=gnu++17" }
>+// { dg-do compile { target c++17 } }
>+
>+#include <variant>
>+#include <utility>
>+
>+
>+template<std::size_t I>
>+struct S {
>+};
>+
>+template <std::size_t... Is>
>+void f_impl(std::index_sequence<Is...>)
>+{
>+	using V = std::variant<S<Is>...>;
>+	static_assert(sizeof(V) == 2);

It might be worth also calling f<256>() and doing:

template <std::size_t... Is>
void f_impl(std::index_sequence<Is...> is)
{
  using V = std::variant<S<Is>...>;

  // For a variant of 255 alternatives the valid indices are [0,254]
  // and index 255 means valueless-by-exception, so fits in one byte.
  if constexpr (std::variant_size_v<V> <= 255)
    static_assert(sizeof(V) == 2)
  else
    static_assert(sizeof(V) > 2)
}

Just to check we don't introduce an off-by-one error in the *other*
direction in future. What do you think?

To be really portable we would use numeric_limits<unsigned char>::max()
but we don't need to worry about non-8-bit char in our implementation.

>+}
>+
>+template <std::size_t I>
>+void f()
>+{
>+	f_impl(std::make_index_sequence<I>{});
>+}
>+
>+int main()
>+{
>+	f<254>();
>+	f<255>();
>+}



More information about the Libstdc++ mailing list