值结构上的 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:
- 在解决方案中创建 C# class 库项目,其中包含名为 Class1.cs 的单个文件,其内容如下 (A)。我给图书馆打了电话"Blah"
- 在包含名为 TestStruct.h 的单个文件的解决方案中创建 C++/CLI 控制台应用程序,其内容如下 (B)。我调用了控制台项目"ValueStructInterfaceIssueCppCli"
- 生成解决方案时会产生以下错误:
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;
};
};
}
在 C++/CLI 中在值类型结构上实现接口时出现问题,其中接口上的方法之一恰好具有需要 ref 的方法签名。我相信我使用了正确的语法,但编译器崩溃了。我让它编译的唯一方法是删除 where 约束。我在 C++/CLI 中的语法有什么问题一定是做错了什么:
解决方案TestSomething.sln:
- 在解决方案中创建 C# class 库项目,其中包含名为 Class1.cs 的单个文件,其内容如下 (A)。我给图书馆打了电话"Blah"
- 在包含名为 TestStruct.h 的单个文件的解决方案中创建 C++/CLI 控制台应用程序,其内容如下 (B)。我调用了控制台项目"ValueStructInterfaceIssueCppCli"
- 生成解决方案时会产生以下错误:
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;
};
};
}