2011-12-30 24 views
0

我有一堆在g ++下編譯得很好的模板化代碼,但現在當我嘗試在windows下使用Visual C++ 2010構建時,出現了一堆錯誤。模板專業化與g ++協同工作,但不適用於Visual C++

我有一個模板函數集合,用於從Lua代碼中獲取和設置C++對象中的值。例如,我有這樣的模板:

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

(完整的文件可以發現here

這是此實例:

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 
+0

什麼是'文本區:: GetCharacterSize'的實際簽名? – ildjarn 2011-12-30 22:26:28

+0

用'GetCharacterSize'簽名更新了這個問題。 – Alex 2011-12-30 22:29:21

+0

對我來說看起來像一個編譯器錯誤 - 應該調用第139行上的重載,而是調用第147行上的重載。 – ildjarn 2011-12-30 22:37:33

回答

4

這是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和科莫4.3.10.1 Beta2中(沒有鏈接),但產生與VC++ 2010 SP1以下錯誤:

錯誤C2668: 'foo':曖昧調用重載函數


編輯:至於解決方法,它的醜陋,但我能想到隨便的唯一的事情就是這樣,沒有超載涉及使用額外的間接層:

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

實際上,這只不過是隻給每個不同過載不同的名稱...

+0

有沒有辦法解決它? – Alex 2011-12-30 22:59:30

+0

如果這是一個已知和可證明的錯誤,有沒有人提交給MS? – 2011-12-31 10:24:12

+0

@CodyGray,我沒有,但我不知道在哪裏提交這樣的錯誤,或者如何檢查它是否是一個已知問題。 – Alex 2012-01-04 00:48:15

1

如果您可以強制用戶選擇函數的實際返回類型,則以下工作。也許,這將是對你有用:

#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()