编译器报告的模板替换期间出错

Error during template substitution reported by compiler

我看到一个正确的构建错误,但由于替换失败不是错误规则,我预计会忽略一些内容:

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);

编译器正在尝试实例化我添加了注释的函数,它没有这样做是正确的。我不明白的是,如果我删除它,那么编译器 将 select 正确的函数 (header 末尾的专业化)和继续快乐地前进。

在我看来,我看到的错误是在替换期间发生的,因此编译器应该默默地丢弃 std::vector<T> 候选并返回到专业化。为什么这没有发生?

发生这种情况是因为 SFINAE 仅适用于 "immediate context",即模板参数本身。

通过将有问题的实例化移动到模板参数中,可以将错误转化为替换失败,如下所示:

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

代码现在编译成功,并选择了适当的 clr_cast 重载。