Это похоже на ошибку компилятора, но дело настолько простое, что я немного скептически отношусь, поэтому я ищу подтверждение. Воспроизводится с VS2010 и VS2012.
Приведенный ниже пример не компилируется. Эта ошибка дана:
Ошибка 1 ошибка C2440: «приведение типа»: невозможно преобразовать из
‘ConvertibleToAny’ в ‘OtherType<_Ty> ‘test.cpp 40
Если вы переместите позицию конструктора перемещения OtherType(ThisType &&)
над конструктором OtherType( int )
Вдруг компилируется.
#include "stdafx.h"#include <string>
using namespace std;
template<class _Ty>
struct OtherType
{
typedef OtherType<_Ty> ThisType;
OtherType()
{
}
OtherType( int )
{
}
// The move constructor
OtherType(ThisType && )
{
}
};
struct ConvertibleToAny
{
template <class AnyType>
operator AnyType()
{
return AnyType();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
(OtherType<wstring>) ConvertibleToAny();
return 0;
}
Это ошибка или это ожидаемое поведение? Если ожидается, пожалуйста, процитируйте соответствующий абзац из спецификации C ++ 11.
Я уже опубликовал это как ошибку в Microsoft Connect, нажмите здесь, чтобы открыть его.
Ваше выражение
(OtherType<wstring>) ConvertibleToAny()
является унарным явным приведением (5.4) из временного пользовательского типа к пользовательскому типу, интерпретируемому в 5.4: 4 как static_cast
:
static_cast<OtherType<wstring>>(ConvertibleToAny())
который согласно 5.2.9: 4 имеет смысл инициализации временной переменной t
:
OtherType<wstring> t(ConvertibleToAny())
Это прямая инициализация (8.5: 15) и как таковые (8.5: 16) все конструкторы с одним аргументом OtherType
участвовать в разрешении перегрузки согласно правилам 13.3.1.3.
После 13.3: 2 оба int
и конструкторы перемещения доступны и являются жизнеспособными согласно 13.3.2, поэтому у нас есть две возможные последовательности неявного преобразования (13.3.3.1) для одного аргумента:
ConvertibleToAny [temporary] -> int
ConvertibleToAny [temporary] -> OtherType<wstring> &&
Следуя 13.3.3.1.2, между этими последовательностями нет упорядочения, поэтому не существует наилучшей жизнеспособной функции, происходит сбой разрешения перегрузки (13.3: 3), и программа имеет неправильную форму.
Если выполнена функция преобразования (12.3.2) explicit
(12.3.2: 2), тогда он рассматривается только для прямой инициализации. Хотя последовательности неявного преобразования (13.3.3.1) являются неявными преобразованиями (4: 3) и, таким образом, включают инициализацию копирования, цель стандарта в примере 12.3.2: 2 состоит в том, что в этом случае следует учитывать функции явного преобразования. ; как таковой, снова кажется, что разрешение перегрузки должно потерпеть неудачу.
Других решений пока нет …