Не можете преобразовать из типа х в тип х? - PullRequest
11 голосов
/ 23 декабря 2011

При компиляции (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 такой ошибки нет.

Это ошибка или я что-то не так делаю?

РЕДАКТИРОВАТЬ: Итак, если это ошибка, кто-нибудь знает, как это решить? Может быть, с помощью приведения? Мне нужен этот код для компиляции ...

Ответы [ 4 ]

4 голосов
/ 23 декабря 2011

Это ошибка компилятора.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, которое должно ссылаться на базовый класс.

Добавление определения типа не помогло, равно как и предварительное объявление struct A, равно как и квалификация имени как ::A или struct 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

1 голос
/ 23 декабря 2011

Похоже на ошибку - она ​​отлично компилируется на Comeau (http://www.comeaucomputing.com/tryitout).

1 голос
/ 23 декабря 2011

Я не уверен, является ли это ошибкой компилятора или нет, но по крайней мере это задокументировано на 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;
}
0 голосов
/ 23 декабря 2011

Я попытался отследить проблему, и теперь кажется, что даже нет необходимости иметь шаблонные функции или вложенные структуры, чтобы вызвать эту странную ошибку.

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
    }
};

Глядя на приведенный выше фрагмент кода, становится очевидным, что это действительно ошибка компилятора (на мой взгляд).

...