从课堂外调用时,为什么会出现转换错误?

时间:2015-01-22 12:21:22

标签: .net generics c++-cli

我有一堂课,我正在尝试编写一些单元测试,但我遇到了转换错误:

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
    }

我可以在被测试的类中以相同的方式调用此方法,并且它工作正常,所以当我从单元测试中调用它时为什么会失败?

2 个答案:

答案 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^ dataT^ data constconst 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。