Специализация шаблонов работает с g ++, но не с Visual C ++ - PullRequest
0 голосов
/ 31 декабря 2011

У меня есть куча шаблонного кода, который прекрасно компилируется под g ++, но теперь, когда я пытаюсь собрать под windows с Visual C ++ 2010, я получаю кучу ошибок.

У меня есть коллекция шаблонных функций для получения и установки значений в объектах C ++ из кода Lua.Например, у меня есть этот шаблон:

//        Class       Return type Getter function
template <typename T, typename U, U (T::*Getter)() const>
int luaU_get(lua_State* L)
{
    T* obj = luaW_check<T>(L, 1); // Gets userdata from stack and checks if it's of type T
    luaU_push(L, (obj->*Getter)()); // Runs the getter function specified in the template, and pushes the
    return 1;
}

(полный файл можно найти здесь )

, который создается здесь:

static luaL_reg TextArea_MT[] =
{
    //                             Class     Return type   Getter function
    { "GetCharacterSize", luaU_get<TextArea, unsigned int, &TextArea::GetCharacterSize> },
    { NULL, NULL }
};

Подпись этого геттера выглядит следующим образом:

unsigned int GetCharacterSize() const;

Я получаю кучу ошибок, подобных этой:

2>C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\game\lua\LuaTextArea.cpp(103): error C2440: 'specialization' : cannot convert from 'unsigned int (__thiscall ag::ui::TextArea::* )(void) const' to 'unsigned int *(__thiscall ag::ui::TextArea::* const )(void) const'
2>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
2>C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\game\lua\LuaTextArea.cpp(103): error C2973: 'luaU_get' : invalid template argument 'unsigned int (__thiscall ag::ui::TextArea::* )(void) const'
2>          C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\extern\LuaWrapper\LuaWrapperUtil.hpp(147) : see declaration of 'luaU_get'
2>C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\game\lua\LuaTextArea.cpp(103): error C2440: 'specialization' : cannot convert from 'unsigned int (__thiscall ag::ui::TextArea::* )(void) const' to 'unsigned int *ag::ui::TextArea::* const '
2>          There is no context in which this conversion is possible
2>C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\game\lua\LuaTextArea.cpp(103): error C2973: 'luaU_get' : invalid template argument 'unsigned int (__thiscall ag::ui::TextArea::* )(void) const'
2>          C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\extern\LuaWrapper\LuaWrapperUtil.hpp(131) : see declaration of 'luaU_get'
2>C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\game\lua\LuaTextArea.cpp(103): error C2440: 'specialization' : cannot convert from 'unsigned int (__thiscall ag::ui::TextArea::* )(void) const' to 'unsigned int ag::ui::TextArea::* const '
2>          There is no context in which this conversion is possible
2>C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\game\lua\LuaTextArea.cpp(103): error C2973: 'luaU_get' : invalid template argument 'unsigned int (__thiscall ag::ui::TextArea::* )(void) const'
2>          C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\extern\LuaWrapper\LuaWrapperUtil.hpp(123) : see declaration of 'luaU_get'
2>C:\Users\Alex\Documents\Visual Studio 2010\Projects\game\dev\src\game\lua\LuaTextArea.cpp(103): error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'lua_CFunction'
2>          None of the functions with this name in scope match the target type

Ответы [ 2 ]

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

Это ошибка компилятора в VC ++.Действителен следующий код:

#include <iostream>

struct TextArea
{
    unsigned GetCharacterSize() const { return 0; }
};

template<typename T, typename U, U (T::*)() const>
int foo()
{
    return 1;
}

template<typename T, typename U, U* (T::*)() const>
int foo()
{
    return 2;
}

int main()
{
    std::cout << foo<TextArea, unsigned, &TextArea::GetCharacterSize>() << '\n';
}

И компилируется с GCC 4.3.4 , GCC 4.5.1 и Comeau 4.3.10.1 Beta2 (без ссылки), но выдает следующую ошибку с VC ++ 2010 SP1:

ошибка C2668: 'foo': неоднозначный вызов перегруженной функции


EDIT: Что касается обходного пути, это некрасиво, но единственное, что я могу придумать, - это использовать дополнительный уровень косвенности, чтобы избежать перегрузки:

#include <iostream>

struct WithPointer
{
    unsigned* GetCharacterSize() const { return nullptr; }
};

struct WithoutPointer
{
    unsigned GetCharacterSize() const { return 0u; }
};

template<bool UsePointerImplB>
struct kludge
{
    template<typename T, typename U, U (T::*Getter)() const>
    static int foo() { return 1; }
};

template<>
struct kludge<true>
{
    template<typename T, typename U, U* (T::*Getter)() const>
    static int foo() { return 2; }
};

int main()
{
    std::cout
        << kludge<false>::foo<WithoutPointer, unsigned, &WithoutPointer::GetCharacterSize>() << '\n'
        << kludge<true>::foo<WithPointer, unsigned, &WithPointer::GetCharacterSize>() << '\n';
}

Фактически это ничем не отличается отпросто присваивая каждой перегрузке свое имя ...

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

Если вы можете заставить пользователя выбрать фактический тип возврата функции, работает следующее. Может быть, вам будет полезно:

#include <iostream>

struct FooBar
{
  int Foo( void ) const
  {
   std::cout << "FooBar::Foo()" << std::endl;
   return ( 0 );
  }
  int * Bar( void ) const
  {
   std::cout << "FooBar::Bar()" << std::endl;
   return ( 0 );
  }
};

template< typename P00, typename P01, P01(P00::*p02)( void ) const >
void Call()
{
 P00 lT;
 ( lT.*p02 )();
}

int main( void )
{
 Call< FooBar, int, &FooBar::Foo > ();
 Call< FooBar, int*, &FooBar::Bar > ();

 return( 0 );
}

Вывод программы:

FooBar::Foo()
FooBar::Bar()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...