[libcxx-commits] [libcxx] r366022 - Avoid eager template instantiation caused by the variant narrowing checks.

Eric Fiselier via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jul 14 11:21:16 PDT 2019


Author: ericwf
Date: Sun Jul 14 11:21:15 2019
New Revision: 366022

URL: http://llvm.org/viewvc/llvm-project?rev=366022&view=rev
Log:
Avoid eager template instantiation caused by the variant narrowing checks.

The standard disallows narrowing conversions when constructing a variant.
This is checked by attempting to perform braced initialization of the
destination type from the argument type. However, braced initialization
can force the compiler (mostly clang) to eagerly instantiate the
constructors of the destintation type -- which can lead to errors in
a non-immediate context.

However, as variant is currently specified, the narrowing checks only
observably apply when the destination type is arithmetic. Meaning we can
skip the check for class types. Hense avoiding the hard errors.

In order to cause fewer build breakages, this patch avoids the narrowing
check except when the destination type is arithmetic.

Modified:
    libcxx/trunk/include/variant
    libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp

Modified: libcxx/trunk/include/variant
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/variant?rev=366022&r1=366021&r2=366022&view=diff
==============================================================================
--- libcxx/trunk/include/variant (original)
+++ libcxx/trunk/include/variant Sun Jul 14 11:21:15 2019
@@ -1095,19 +1095,39 @@ struct __overload;
 template <>
 struct __overload<> { void operator()() const; };
 
+
+
+struct __no_narrowing_check {
+  template <class _Dest, class _Source>
+  using _Apply = __identity<_Dest>;
+};
+
+struct __narrowing_check {
+  template <class _Dest>
+  static auto __test_impl(_Dest (&&)[1]) -> __identity<_Dest>;
+  template <class _Dest, class _Source>
+  using _Apply = decltype(__test_impl<_Dest>({std::declval<_Source>()}));
+};
+
+template <class _Dest, class _Source>
+using __check_for_narrowing = typename _If<
+#ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
+    false &&
+#endif
+    is_arithmetic<_Dest>::value,
+    __narrowing_check,
+    __no_narrowing_check
+    >::template _Apply<_Dest, _Source>;
+
+
 template <class _Tp, class... _Types>
 struct __overload<_Tp, _Types...> : __overload<_Types...> {
   using __overload<_Types...>::operator();
 
-  static auto __test(_Tp (&&)[1]) -> __identity<_Tp>;
-
   template <class _Up>
-  auto operator()(_Tp, _Up&& __t) const
-#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT
-      -> decltype(__test({ _VSTD::forward<_Up>(__t) }));
-#else
-      -> __identity<_Tp>;
-#endif
+  auto operator()(_Tp, _Up&&) const ->
+
+  __check_for_narrowing<_Tp, _Up>;
 };
 
 template <class _Base, class _Tp>

Modified: libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp?rev=366022&r1=366021&r2=366022&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp Sun Jul 14 11:21:15 2019
@@ -177,10 +177,22 @@ void test_T_ctor_basic() {
 #endif
 }
 
+struct BoomOnInt {
+  template <class T>
+  constexpr BoomOnInt(T) { static_assert(!std::is_same<T, int>::value, ""); }
+};
+
+void test_no_narrowing_check_for_class_types() {
+  using V = std::variant<int, BoomOnInt>;
+  V v(42);
+  assert(v.index() == 0);
+  assert(std::get<0>(v) == 42);
+}
+
 int main(int, char**) {
   test_T_ctor_basic();
   test_T_ctor_noexcept();
   test_T_ctor_sfinae();
-
+  test_no_narrowing_check_for_class_types();
   return 0;
 }




More information about the libcxx-commits mailing list