【问题标题】:Cannot convert from type x to type x?无法从类型 x 转换为类型 x?
【发布时间】:2011-12-23 15:31:24
【问题描述】:

编译(Microsoft Visual C++ 2005 Express)这段代码时:

struct A
{
    template< typename T > static A Foo( void ) { return A(); }
    struct S
    {
        template< typename T > static S GetInstance( void )
        {
            S Result;
            Result.m_funcFoo = &A::Foo< T >;
            return Result;
        }
        A ( *m_funcFoo )( void );
    };
};

int main(int argc, char* argv[])
{
    A::S::GetInstance< int >();
}

我收到 C2440 错误:

'=': 无法从'A (__cdecl *)(void)' 转换为'A (__cdecl *)(void)'

这对我来说没有意义。错误文本中命名的两种类型显然是相同的。 还有,把Foo的返回值改成int,也没有这个错误。

这是一个错误还是我做错了什么?

编辑: 那么,如果这是一个错误,有谁知道如何解决这个问题?也许通过使用演员表?我需要这段代码来编译...

【问题讨论】:

  • 一开始我还以为是A (*)(void)A (A::*)(void)不同,没想到那样做。

标签: c++ visual-studio function-pointers


【解决方案1】:

这是一个编译器错误。 VC++ 正在做一些非常奇怪的事情。

例如,这会生成一个非常不同的错误消息:

struct A
{
    template< typename T > static struct A Foo( void ) { return A(); }
    struct S
    {
        template< typename T > static S GetInstance( void )
        {
            S Result;
            Result.m_funcFoo = &A::Foo< T >;
            return Result;
        }
        A ( *m_funcFoo )( void );
    };
};

sourceFile.cpp(5) : error C3856: 'A::Foo': class is not a class template

这行得通:

struct X {};

struct A
{
    template< typename T > static X Foo( void ) { return X(); }
    struct S
    {
        template< typename T > static S GetInstance( void )
        {
            S Result;
            Result.m_funcFoo = &A::Foo< T >;
            return Result;
        }
        X ( *m_funcFoo )( void );
    };
};

显然它被 A 这个名字弄糊涂了,它应该是指基类。

添加 typedef 没有帮助,struct A 的前向声明也没有帮助,将名称限定为 ::Astruct A 也没有帮助。

奇怪的是,VC++7 编译得很好。

解决方法:像这样更改它:

struct A
{
    template< typename T > static A Foo( void ) { return A(); }

    struct S;
};

struct A::S
{
    template< typename T > static S GetInstance( void )
    {
        S Result;
        Result.m_funcFoo = &A::Foo< T >;
        return Result;
    }
    A ( *m_funcFoo )( void );
};

反转结果,现在 VC++8 编译正常,VC++7 生成相同的错误消息。

我认为不完整的类型和完成后的相同类型之间存在类型标识问题。

所有测试都使用 Dinkumware Multi-Compiler Test Tool 运行

【讨论】:

    【解决方案2】:

    我不确定这是否是编译器错误,但至少它记录在 msdn.
    我手头没有 2005 编译器,但如果这样写,vs2010 会编译你的代码:

    struct A
    {
        template< typename T > static A Foo( void ) { return A(); }
        struct S
        {
            A ( *m_funcFoo )( void );       
    
            template< typename T > static S GetInstance( void );
        };
    };
    
    template< typename T > 
    A::S A::S::GetInstance( void )
    {
        S Result;
        Result.m_funcFoo = &A::Foo< T >;
        return Result;
    }
    

    【讨论】:

    • @mkaes 你真的实例化了A::S::GetInstance(例如通过调用它)吗?我在 VS2005 和 VS2010 中都测试了你的代码——仍然是同样的错误。
    【解决方案3】:

    看起来像一个错误——它在 Comeau (http://www.comeaucomputing.com/tryitout) 上编译得很好。

    【讨论】:

      【解决方案4】:

      我试图追查问题,现在似乎甚至不需要模板函数或嵌套结构来产生这个奇怪的错误。

      struct A
      {
          typedef A ( * SimpleFuncPtr )( void );
          static void Foo( void )
          {
              SimpleFuncPtr func1 = 0;        // Ok.
              SimpleFuncPtr func2 = func1;    // Ok.
              A ( * func3 )( void ) = func1;  // C2440 on both VS2005 and VS2010
          }
      };
      

      通过查看上面的代码,很明显它确实是一个编译器错误(在我看来)。

      【讨论】:

      • 问题出在不完整的类型上,并在 mkaes 提供的链接中进行了描述(即,因为在函数指针定义时类型不完整,编译器会选择稍后的特定调用约定定义完整类型时覆盖)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 1970-01-01
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多