https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63723

            Bug ID: 63723
           Summary: Narrowing conversion allowed in braced init list in
                    SFINAE context
           Product: gcc
           Version: 4.9.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tavianator at gmail dot com

Created attachment 33877
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33877&action=edit
Preprocessed source

GCC allows narrowing conversions in braced init lists with only a warning.  The
documentation suggests that this extension doesn't apply in SFINAE contexts,
but it appears to be wrong:

$ cat foo.cpp
#include <type_traits>
#include <utility>

template <typename From, typename To>
class is_list_convertible_helper
{
  template <typename To2>
  static void requires_conversion(To2 t);

  template <typename From2, typename To2,
      typename = decltype(requires_conversion<To2>({std::declval<From2>()}))>
  //                                               ^ Braced initializer
  static std::true_type helper(int);

  template <typename From2, typename To2>
  static std::false_type helper(...);

public:
  using type = decltype(helper<From, To>(0));
};

template <typename From, typename To>
class is_list_convertible
  : public is_list_convertible_helper<From, To>::type
{ };

static_assert(!is_list_convertible<double, int>::value,
    "double -> int is narrowing!");

$ g++ -std=c++11 foo.cpp
foo.cpp: In substitution of ‘template<class From2, class To2, class> static
std::true_type is_list_convertible_helper<From, To>::helper(int) [with From2 =
double; To2 = int; <template-parameter-1-3> = <missing>]’:
foo.cpp:18:31:   required from ‘class is_list_convertible_helper<double, int>’
foo.cpp:22:7:   required from ‘class is_list_convertible<double, int>’
foo.cpp:26:48:   required from here
foo.cpp:10:46: warning: narrowing conversion of ‘std::declval<double>()’ from
‘double’ to ‘int’ inside { } [-Wnarrowing]
       typename = decltype(requires_conversion<To2>({std::declval<From2>()}))>
                                              ^
foo.cpp:26:1: error: static assertion failed: double -> int is narrowing!
 static_assert(!is_list_convertible<double, int>::value,
 ^

Reply via email to