2013-06-06 2 views
5

Вчера в ходе ответа на чужой вопрос, я был удивления обнаружил, что GCC 4.7.2 <type_traits> содержал шаблон std::is_explicitly_convertible<From,To> черта , определенную как обратная std::is_constructible_convertible<To,From>:"static_cast <To> (from)" если и только если "To to {from}", или нет?

/// is_explicitly_convertible 
template<typename _From, typename _To> 
struct is_explicitly_convertible 
: public is_constructible<_To, _From> 
{ }; 

Ищет бумажный след , Я тогда обнаружил, что эта черта не должна иметь . A bug был поднят против его включения в ту версию стандартной библиотеки C++ 11 Standard, которая была удалена в gcc 4.8.0.

Это сообщение об ошибке указал, что std::is_explicitly_convertible (с было предусмотрено в более ранних проектах ++ 0x стандарта C), был удален из проекта стандарта по N3047 в 2010 году

N3047 объясняет это о- Поворот:

Оставшийся вопрос в том, каким образом также пострадал is_explicitly_convertible признак. Основные варианты:

  1. Fix is_explicitly_convertible, вернувшись к текущему static_cast выражение, больше не делает is_explicitly_convertible зависимой от is_constructible.
  2. Удалить is_explicitly_convertible со стандарта.

Первый выбор был рассмотрен, но оказалось, что существует совершенно иное понимание того, что означает «явно конвертируемый». Хотя некоторые считают, что static_cast правильно выражают это, другие полагали, что фиксированный is_constructible обеспечит лучшее значение для is_explicitly_convertible. Поэтому в настоящем документе рекомендуется удалить is_explicitly_convertible из рабочего чертежа. Это не должно наносить вреда сейчас, потому что ничто не зависит от этого специального определения. И если окажется, что черта все равно будет полезна, ее можно было бы добавить в другой редакции стандарта.

Это объяснение кажется, подразумевает, что стороны несогласия знали случаев, в которых, по выражению from типа From, static_cast<To>(from) бы компилировать в то время как To to{from}; не будет; или наоборот.

Есть ли такие случаи?

Если нет, может кто-нибудь авторитетно (не умозрительно, пожалуйста) объяснить различие между static_castibility от From к To и конструктивность To из From, который был в игре здесь?

+2

* не * использовать 'T для { from} 'в общем коде - он может давать значительно разные результаты: от T до (from);'. – Xeo

+0

Можете ли вы указать мне где-нибудь, что иллюстрирует это? –

+1

Think 'std :: vector ' например - 'T to {10}' даст одноэлементный вектор, а 'T t (10)' даст 10-элементный вектор. – Xeo

ответ

2

Во-первых, некоторый контрольный код.TestA ваше явное построение и TestB ваш явный static_cast ING:

template<typename To, typename From> 
To TestA(From from) { 
    To to{from}; 
    return to; 
} 
template<typename To, typename From> 
To TestB(From from) { 
    return static_cast<To>(from); 
} 

static_cast позволяет понижающее приведение в объектной иерархии, в то время как явная конструкция не будет:

struct Base {}; 
struct Derived:Base {}; 

int main() { 
    Base* b; 
    // TestA<Derived*>(b); -- fails to compile 
    TestB<Derived*>(b); 
} 
+0

Действительно! Спасибо. –