Visual studio 2013 在Visual C+中,CLI中委托的用法不同+;2013

Visual studio 2013 在Visual C+中,CLI中委托的用法不同+;2013,visual-studio-2013,delegates,c++-cli,Visual Studio 2013,Delegates,C++ Cli,我们有一个树结构的实现。该树由从MachineItemNode派生的节点组成。我们使用System::Func委托实现了一些节点过滤。这使我们能够在树中搜索与指定派生类型MachineItemNode和自定义谓词匹配的节点 下面的实现在VS 2008编译器(使用.Net 3.5)上运行良好, 但是使用VS2013编译器(和.NET4.0),我得到了一个编译器错误(见下文) public ref class MachineItemNode { 公众: 泛型,其中T:MachineItemNode

我们有一个树结构的实现。该树由从MachineItemNode派生的节点组成。我们使用System::Func委托实现了一些节点过滤。这使我们能够在树中搜索与指定派生类型MachineItemNode和自定义谓词匹配的节点

下面的实现在VS 2008编译器(使用.Net 3.5)上运行良好, 但是使用VS2013编译器(和.NET4.0),我得到了一个编译器错误(见下文)

public ref class MachineItemNode
{
公众:
泛型,其中T:MachineItemNode
T FindFirstBelow()
{
System::Func^filter=gcnew System::Func(this,&MachineItemNode::AlwaysTrue);
return FindFirstBelow(filter);//错误C2670:'MachineItemNode::FindFirstBelow':函数模板无法从类型'System::Func^'转换参数1
}
泛型,其中T:MachineItemNode
T FindFirstBlow(系统::函数^filter)
{
如果(此->IsNode())
{
T结果=安全浇铸(本);
if(过滤器(结果))
{
返回结果;
}
}
对于每个(子项中的MachineItemNode^子项)
{
T result=child->FindFirstBelow(过滤器);
如果(结果!=nullptr)
{
返回结果;
}
}
返回T();
}
泛型,其中T:MachineItemNode
布尔阿尔韦斯特雷(T)
{
返回true;
}
泛型,其中T:MachineItemNode
bool IsNode()
{
返回T::typeid->IsAssignableFrom(this->GetType());
}
私人:列出^Children;
};
在我看来,一切都应该很好。过滤器的类型正是以下FindFirstBlow参数化版本所需的类型

我的代码是否有问题,或者这是Visual Studio编译器中的错误

致意 Michael

无法从'System::Func^'转换为'System::Func'^
这里的诊断是System::Func有两个定义,它们来自不同的程序集。这是可能的,因为.NET 4.5,他们将类型从System.Core.dll移动到mscorlib.dll。有一种非常巧妙的机制可以使这种破坏性的更改不可见,用于构建项目的引用程序集包含一个[TypeForwardTo]指令,告诉编译器它位于另一个建筑中

但如果不使用正确的引用程序集,则会像这样中断。这在C++/CLI项目中并不完全罕见。当编译器实际使用C:\Windows\Microsoft.NET\Framework中的程序集而不是存储在C:\Program Files(x86)\Reference Assemblys\Microsoft\Framework\.NETFramework\vx.y(其中x.y是目标框架)中的正确程序集时,会出现错误。程序员究竟是如何陷入这种麻烦的,我并不十分清楚,他们从来没有告诉我

首先要做的是检查项目的引用程序集,使用“项目>属性>公用属性>引用”,然后逐个选择“引用”框中列出的程序集。验证显示的“相对路径”属性。删除引用并在错误时将其添加回。请注意仍然有对System.Core的3.5版本的引用

接下来要做的事情是使用指令检查源代码中的
。这很脆弱,而且有从错误目录中提取程序集的诀窍。赞成使用项目配置。请注意,#using隐藏在编译器的include/msclr目录中存储的.h文件中,因此也要查看#include


而且mscorlib.dll是有问题的,请注意它如何没有明确地列在项目的参考列表中。使用“工具”>“选项”>“项目和解决方案”>“生成和运行”>“MSBuild项目生成输出详细信息”生成详细的生成跟踪。重建项目并在输出窗口中搜索生成跟踪以查找“mscorlib”。

@Petr:显然不是。添加丢失的声明后(执行可以实际编译的复制后代码!)我没有收到编译器的任何抱怨。我也没想到会有。你要记录所有的错误,也应该有一个C2440,这是更多的信息。你需要补充什么?我没有其他错误。我稍微修改了代码,通过添加一个helper函数
GetAlwaysFilterTrue
,得到了C2440。我现在得到的错误是:错误C2440:“return”:无法从“System::Func^”转换为“System::Func^”1>没有可用的用户定义转换运算符,或者1>指向的类型不相关;转换需要重新解释_cast、C样式cast或函数样式cast这可能是原因,但不幸的是,对我来说,mscorlib的解析似乎是正确的。此外,没有对System.Core的直接引用。下面是详细的构建日志。。。。。。。。。。1> 统一的主要参考“mscorlib,版本=4.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089”。1> 解析的文件路径为“C:\Program Files(x86)\Reference Assembly\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll”。你还有其他想法吗?没有看到你的项目或构建跟踪。在这里,我们尽量避免依赖透视。
public ref class MachineItemNode
{
public:
    generic <typename T> where T : MachineItemNode
    T FindFirstBelow()
    {
        System::Func<T, bool>^ filter = gcnew System::Func<T, bool>(this, &MachineItemNode::AlwaysTrue<T>);
        return FindFirstBelow<T>(filter); // error C2670: 'MachineItemNode::FindFirstBelow' : the function template cannot convert parameter 1 from type 'System::Func<T,bool> ^'
    }

    generic <typename T> where T : MachineItemNode
    T FindFirstBelow(System::Func<T, bool>^ filter)
    {
        if (this->IsNode<T>())
        {
            T result = safe_cast<T>(this);
            if (filter(result))
            {
                return result;
            }
        }

        for each (MachineItemNode^ child in Children)
        {
            T result = child->FindFirstBelow<T>(filter);
            if (result != nullptr)
            {
                return result;
            }
        }

        return T();
    }

    generic <typename T> where T : MachineItemNode
        bool AlwaysTrue(T)
    {
        return true;
    }

    generic <typename T> where T : MachineItemNode
        bool IsNode()
    {
        return T::typeid->IsAssignableFrom(this->GetType());
    }

private: List<MachineItemNode^>^ Children;
};
 cannot convert from 'System::Func<T,bool> ^' to 'System::Func<T,bool> ^