2014-11-02 5 views
7

В C++ 11 введена унифицированная инициализация, которая поставляется с желательной особенностью запрещения неявных суживающих преобразований. Например, ошибка int i{2.2}.Как я могу написать черту типа, чтобы проверить, является ли тип конвертируемым в другое путем не сужающегося преобразования?

К сожалению, для соображений обратной совместимости с C++ 03 GCC с 4.7 дает только предупреждение для них.

ССЗ documentation предполагает, что это расширение не применяется в 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, 
^ 

Замыкание добавления специализаций для каждого сужающегося обращения, есть ли способ сделать эту работу?

+0

Проверить числовые ограничения вручную? – Yakk

+0

@Yakk Какую проверку я бы использовал, точно? Какие конверсии являются и не сужаются, не имеет никакого отношения к фактическому диапазону или точности соответствующих типов. –

+0

@Tavain Запрет правила констант, когда это не связано с точностью/типами? Обнаруживать float-> integer, float-> less precice float, integer-> float, integer-> integer, который не является надмножеством. Все выглядят как черты характера и точность вещей? – Yakk

ответ

0

Проще говоря, это bug в GCC. Ошибка существует с -std=c++11 (хотя она работала в GCC 4.6 с -std=c++0x). Он был исправлен для предстоящего выпуска GCC 5, но, вероятно, он не будет передан в GCC 4.9.