我有一堂课,我正在尝试编写一些单元测试,但我遇到了转换错误:
1>c:\projects\myproj\unittests\UnitTest_MyClass.h(60): error C2664: 'MyClass::MyFunc' : cannot convert parameter 1 from 'GenericCollections::CircularBuffer<T> ^' to 'GenericCollections::CircularBuffer<T> ^'
1> with
1> [
1> T=const MyProj::DataPacket ^
1> ]
1> and
1> [
1> T=MyProj::DataPacket ^const
1> ]
正在测试的类(只是一个片段):
public ref class MyClass
{
protected:
double MyFunc(GenericCollections::CircularBuffer<const MyProj::DataPacket^>^ data, int &firstIndex, int &lastIndex);
单元测试(只是一个片段):
[Test]
public ref class UnitTest_MyClass : public MyClass
{
public:
[Test]
void Test_0001_MyFunc()
{
GenericCollections::CircularBuffer<const MyProj::DataPacket^>^ data = nullptr; // This will eventually be populated with test data
int firstIndex = 0;
int lastIndex = data->Length-1;
double funcResult = MyFunc(data, firstIndex, lastIndex); // causes error C2664
}
我可以在被测试的类中以相同的方式调用此方法,并且它工作正常,所以当我从单元测试中调用它时为什么会失败?
答案 0 :(得分:4)
问题中缺少一个重要的细节,但可以推断出来。这无法编译,因为您通过程序集引用而不是#include导入类型定义。您对此代码进行单元测试的预期方式。
你必须记住const
关键字是一个问题,CLR完全错过了这个概念。只有强制执行它才有意义,当您的代码被另一种托管语言(如VB.NET或C#)使用时,这种情况就不会发生。不具备与本地C ++中使用的const
类似的语言。
CLR中的元数据允许语言通过[modopt]构造向变量和参数类型添加任意属性。 C ++ / CLI编译器在发出Func&lt;&gt;的元数据时会使用它,这可以通过ildasm.exe看到:
MyFunc(class GenericCollections.CircularBuffer`1<
class DataPacket modopt([mscorlib]System.Runtime.CompilerServices.IsConst)
> data,
// etc...
编辑为适合,请注意type参数上发出的[modopt]。然而,这还不足以完全表达 const 可以在本机C ++中应用的各种方式。 数据参数可以是const T^ data
,T^ data const
或const T^ data const
。不是只用那一个[modopt]来表达的东西。
你可能会认为这是一个编译器缺陷,但事实并非如此,这种限制是故意的。他们确实使编译器足够智能,注意const
在这里是不明确的,并生成一个适当的错误消息。
嗯,你能做的不是那么多。 #include类型定义时,它不会成为问题,编译器就可以对声明有足够的了解。也许你可以重新调整你的项目,尽管它并不是非常实用。我对此问题的通常建议是放弃const
在托管代码中有用的概念。事实并非如此,C ++ / CLI是一种互操作语言,这类代码的常用消费者并不了解有关const的bean,因此不会强制执行。
答案 1 :(得分:1)
with
[
T=const Anchor::DataPacket ^
]
and
[
T=Anchor::DataPacket ^const
]
看起来编译器在对const引用的引用和对象的const引用之间混淆了。 C2664的错误描述页面未显示传递const引用集合时显式发生的情况。我想我会尝试从模板中删除const。