C++11引入了统一的初始化,它具有禁止隐式窄化转换的可取特性。例如,int i{2.2}应该是一个错误。
不幸的是,出于与C++03向后兼容的原因,GCC自4.7以来只对此提出了警告.
GCC的文档建议,这个扩展不适用于SFINAE上下文,但它似乎是错误的:
#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!");GCC 4.9.1给出了这个输出
$ 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,
^除了为每一次缩小转换添加专门化之外,是否有一种方法可以使此工作?
发布于 2015-01-27 18:39:03
很简单,这是GCC的错误。自从-std=c++11被支持以来,这个bug就已经存在了(尽管它在GCC 4.6中与-std=c++0x一起工作)。它已经为即将发布的GCC 5版本做好了准备,但很可能不会被提供给GCC 4.9。
https://stackoverflow.com/questions/26705199
复制相似问题