在以下(工作)代碼示例中,使用模板化register_enum()函數遍歷枚舉並調用用戶提供的回調函數以將枚舉值轉換爲c字符串。所有的枚舉都是在一個類中定義的,枚舉到字符串的轉換是通過一個靜態的to_cstring(枚舉)函數完成的。當一個類(如下面的着色器類)有多個枚舉和相應的重載to_cstring(枚舉)函數時,編譯器無法決定哪個是傳遞給register_enum()的正確的to_cstring()函數。我覺得代碼解釋比我能更好...如何在使用std :: function時解決這個<未解析的重載函數類型>錯誤?
#include <functional>
#include <iostream>
// Actual code uses Lua, but for simplification
// I'll hide it in this example.
typedef void lua_State;
class widget
{
public:
enum class TYPE
{
BEGIN = 0,
WINDOW = BEGIN,
BUTTON,
SCROLL,
PROGRESS,
END
};
static const char *to_cstring(const TYPE value)
{
switch (value)
{
case TYPE::WINDOW: return "window";
case TYPE::BUTTON: return "button";
case TYPE::SCROLL: return "scroll";
case TYPE::PROGRESS: return "progress";
default: break;
}
return nullptr;
}
};
class shader
{
public:
enum class FUNC
{
BEGIN = 0,
TRANSLATE = BEGIN,
ROTATE,
SCALE,
COLOR,
COORD,
END
};
enum class WAVEFORM
{
BEGIN = 0,
SINE = BEGIN,
SQUARE,
TRIANGLE,
LINEAR,
NOISE,
END
};
static const char *to_cstring(const FUNC value)
{
switch (value)
{
case FUNC::TRANSLATE: return "translate";
case FUNC::ROTATE: return "rotate";
case FUNC::SCALE: return "scale";
case FUNC::COLOR: return "color";
case FUNC::COORD: return "coord";
default: break;
}
return nullptr;
}
static const char *to_cstring(const WAVEFORM value)
{
switch (value)
{
case WAVEFORM::SINE: return "sine";
case WAVEFORM::SQUARE: return "square";
case WAVEFORM::TRIANGLE: return "triangle";
case WAVEFORM::LINEAR: return "linear";
case WAVEFORM::NOISE: return "noise";
default: break;
}
return nullptr;
}
};
// Increment an enum value.
// My compiler (g++ 4.6) doesn't support type_traits for enumerations, so
// here I just static_cast the enum value to int... Something to be fixed
// later...
template < class E >
E &enum_increment(E &value)
{
return value = (value == E::END) ? E::BEGIN : E(static_cast<int>(value) + 1);
}
widget::TYPE &operator++(widget::TYPE &e)
{
return enum_increment<widget::TYPE>(e);
}
shader::FUNC &operator++(shader::FUNC &e)
{
return enum_increment<shader::FUNC>(e);
}
shader::WAVEFORM &operator++(shader::WAVEFORM &e)
{
return enum_increment<shader::WAVEFORM>(e);
}
// Register the enumeration with Lua
template< class E >
void register_enum(lua_State *L, const char *table_name, std::function< const char*(E) > to_cstring)
{
(void)L; // Not used in this example.
// Actual code creates a table in Lua and sets table[ to_cstring(i) ] = i
for (auto i = E::BEGIN; i < E::END; ++i)
{
// For now, assume to_cstring can't return nullptr...
const char *key = to_cstring(i);
const int value = static_cast<int>(i);
std::cout << table_name << "." << key << " = " << value << std::endl;
}
}
int main(int argc, char **argv)
{
(void)argc; (void)argv;
lua_State *L = nullptr;
// Only one to_cstring function in widget class so this works...
register_enum<widget::TYPE>(L, "widgets", widget::to_cstring);
// ... but these don't know which to_cstring to use.
register_enum<shader::FUNC>(L, "functions", shader::to_cstring);
//register_enum<shader::WAVEFORM>(L, "waveforms", shader::to_cstring);
return 0;
}
編譯器輸出:
$ g++ -std=c++0x -Wall -Wextra -pedantic test.cpp -o test && ./test
test.cpp: In function ‘int main(int, char**)’:
test.cpp:140:69: error: no matching function for call to ‘register_enum(lua_State*&, const char [10], <unresolved overloaded function type>)’
test.cpp:140:69: note: candidate is:
test.cpp:117:7: note: template<class E> void register_enum(lua_State*, const char*, std::function<const char*(E)>)
我如何通過正確的to_cstring功能register_enum()?我意識到我可以重新命名個人to_cstring()函數,但如果可能的話,我想避免這種情況。也許我的設計很臭,你可以推薦一個更好的方法。
我的問題看起來類似於Calling overloaded function using templates (unresolved overloaded function type compiler error)和How to get the address of an overloaded member function?但到目前爲止,我無法將這些信息應用到我的特定問題。
爲什麼downvote?這是一個更簡單的解決方案。 – xcski 2018-01-18 23:19:02