Ошибка при замене шаблона, сообщенная компилятором

Я вижу ошибку сборки, которая является правильной, но что-то, что я ожидал бы игнорировать из-за правила "Ошибка замены не является ошибкой":

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(895): error C3699: '&&': cannot use this indirection on type 'System::String ^'
RemoteWrapper.cpp(41): note: see reference to class template instantiation 'std::vector<System::String ^,std::allocator<_Ty>>' being compiled
        with
        [
            _Ty=System::String ^
        ]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\vector(918): error C3699: '&&': cannot use this indirection on type 'System::String ^'

Вот код, который упоминает ошибка:

std::string nativeString;
String^ clrString = clr_cast<String^>(nativeString);

Вот clr_cast шаблоны:

template<typename TReturn, typename TSource>
TReturn clr_cast(TSource value)
{
    return (TReturn)value;
}

template<typename TReturn, typename TSource, typename = std::enable_if<!std::is_same<TReturn, TSource>>::value>
std::vector<TReturn> clr_cast(array<TSource>^ value)
{
    [iterate and cast]
}

template<typename T>
std::vector<T> clr_cast(array<T>^ value)
{
    [memcpy]
}

template<typename TReturn, typename TSource, typename = std::enable_if<!std::is_same<TReturn, TSource>>::value>
array<TReturn>^ clr_cast(std::vector<TSource> value)
{
    [iterate and cast]
}

template<typename T>
array<T>^ clr_cast(std::vector<T> value) // this is the problematic function
{
    [memcpy]
}

template<> std::string clr_cast(System::String^ value);
template<> System::String^ clr_cast(std::string value);

Компилятор пытается создать экземпляр функции, к которой я добавил комментарий, и это правильно, что он этого не делает. Чего я не понимаю, так это того, что если я удалю его, то компилятор выберет правильную функцию (специализация в конце заголовка) и продолжит счастливо.

Мне кажется, что ошибка, которую я вижу, происходит во время замены, и поэтому компилятор должен молча отбросить std::vector<T> кандидат и отступить от специализации. Почему этого не происходит?

1 ответ

Решение

Это происходило потому, что SFINAE применяется только к "непосредственному контексту", то есть к самому параметру шаблона.

Ошибка может быть превращена в ошибку замещения путем перемещения проблемной реализации в параметры шаблона, например:

template<typename T, typename = T&&>
array<T>^ clr_cast(std::vector<T> value)
function
{
    [memcpy]
}

Теперь код успешно компилируется, а соответствующий clr_cast перегрузка выбрана.

Другие вопросы по тегам