值结构上的 C++/CLI 实现具有 where t 的接口:结构约束使编译器崩溃

C++/CLI on value struct implementing an interface that has a where t : struct constraint crashes compiler

在 C++/CLI 中在值类型结构上实现接口时出现问题,其中接口上的方法之一恰好具有需要 ref 的方法签名。我相信我使用了正确的语法,但编译器崩溃了。我让它编译的唯一方法是删除 where 约束。我在 C++/CLI 中的语法有什么问题一定是做错了什么:

解决方案TestSomething.sln:

  1. 在解决方案中创建 C# class 库项目,其中包含名为 Class1.cs 的单个文件,其内容如下 (A)。我给图书馆打了电话"Blah"
  2. 在包含名为 TestStruct.h 的单个文件的解决方案中创建 C++/CLI 控制台应用程序,其内容如下 (B)。我调用了控制台项目"ValueStructInterfaceIssueCppCli"
  3. 生成解决方案时会产生以下错误:

Error 1 error C1001: An internal error has occurred in the compiler. f:\valuestructinterfaceissuecppcli\TestStruct.h 22 1 ValueStructInterfaceIssueCppCli

在 C# 中我有一个非常简单的界面,这是在 C# class 库项目中,实际上只是一个文件。

Class1.cs (一) 内容

using System;

namespace Blah
{
    public interface IHoopie<T> where T : struct
    {
        void DoSomething(ref T source);
    }
}

然后我在 C++ 的值结构上实现这个接口,很简单:

这是在 C++/CLI 控制台应用程序中,在同一解决方案中有一个对 C# class 库 "blah" 的项目引用。

TestStruct.h (B) 内容

#pragma once
using namespace System;

namespace Blah
{
public value struct TestStruct : public IHoopie<TestStruct> 
{
public:
    double X;
    double Y;
    double Z;

    virtual void DoSomething(TestStruct% source)
    {
        X = 1;
        Y = 2;
        Z = 3;
    };
};
}

然而,当我尝试在 VS 2010 (sp1) 中用 C++/CLI 实现接口时,编译器崩溃了,我也尝试在 VS 2015(更新 3)中编译同样的事情。

Error 2 error C1001: An internal error has occurred in the compiler. ..\valuestructinterfaceissuecppcli\TestStruct.h 22 1 ValueStructInterfaceIssueCppCli

我需要将我的接口限制为仅值类型,但是作为测试,我删除了 C# 接口中的 where 约束,就像这样和上面的 C++ 代码然后顺从了就好了:

public interface IHoopie<T> 
{
    void DoSomething(ref T source);
}

作为另一个测试,我在 C++/CLI 中使用了 "ref struct",它也有效。无论出于何种原因,我都不能在 c# 中使用 "where T : struct",然后在 C++/CLI 中的值结构上实现它。只是看起来很奇怪。我相信我在 C++/CLI 中使用了正确的格式:

virtual void DoSomething(TestStruct% source)

% 对于通过引用传递值类型是正确的,它应该没问题,但我不明白为什么它不能编译。

我也对简单地删除 C# 中的 where 约束有一些担忧。如果 T 恰好是一个对象,那么语法 TestStruct% source 不正确,它必须是 TestStruct%^ 并且当 T 是一个整数时,例如“%^”将无法工作,除非我遗漏了一些东西

更新!!!

ebyRob 在评论中提到了一些给了我想法的东西。我更改了代码以对 T 使用不同的结构,如下所示:

TestStruct.h (B) 内容

public value struct SomeStruct
{
public:
    double x;
};

public value struct TestStruct : public IHoopie<SomeStruct> 
{
private:
    double last_;

public:
    double X;
    double Y;
    double Z;

    virtual void DoSomething(SomeStruct% source)
    {
        X = 1;
        Y = 2;
        Z = 3;
    };
};

修复了编译器崩溃问题....很有趣。需要弄清楚这一点。如果这是答案,将 post 返回。我的猜测(不是一个好猜测)是在 C++/CLI 中使用 .h 文件中的结构作为它自己的声明中的 T 有一些问题吗?这也许就是使编译器崩溃的原因。

请记住,在 C# 中这是完全合乎逻辑的。我在结构定义中说,我希望 TestStruct 实现一个名为 DoSomething 的方法,该方法通过引用获取其自身的值类型。在上下文中,也许这是一个可能的用例(假设 DoSomething 被称为 Copy)

Copy(ref TestStruct source) { /* do some copying */ }

不是真的,但下面的评论中的 Lucas 和 ebyrob 给了我一些想法:

根据调查结果,将 TestStruct 替换为 int 或其他一些结构编译器不再崩溃....表明更多只是一些编译器问题。为了证明这一点,我使用 4.6.1 而不是 4.0 来查看它是否已修复

Retried the original test I noted in post. It DOES compile just fine on .NET 4.6.1 in C+/CLI. @Lucas -> looks like a complier bug as described. Also will not be fixed in VS 2010 obviously but what do I know. Is fixed in 4.6.1 at least.

这里所说的所有理论都是由 ebyrob 提出的,所以感谢 ebyrob 引导我从另一个方向看,即使这是 Lcuas 指出的完全有效的语法,仍然让我走上了道路。

再次感谢大家

在您的实现之上添加一个 IHoopie 实现似乎可以避免编译器错误。我不知道为什么。

#pragma once
using namespace System;

namespace Blah
{
public value struct HoopieAdapter : public IHoopie<int> {
    public: virtual void DoSomething(int% source) {}
};

public value struct TestStruct : public IHoopie<TestStruct> 
{
public:
    double X;
    double Y;
    double Z;

    virtual void DoSomething(TestStruct% source)
    {
        X = 1;
        Y = 2;
        Z = 3;
    };
};
}