C++ 如何解决此问题<;未解析的重载函数类型>;使用std::函数时出错?
在下面的(工作)代码示例中,模板化register_enum()函数用于迭代枚举,并调用用户提供的回调函数将枚举值转换为c字符串。所有枚举都是在一个类中定义的,枚举到字符串的转换是通过静态到字符串(enum)函数完成的。当一个类(如下面的着色器类)具有多个枚举并对应重载到_cstring(enum)函数时,编译器无法确定传递到register _enum()的正确的to _cstring()函数。我觉得代码解释得比我能解释的好C++ 如何解决此问题<;未解析的重载函数类型>;使用std::函数时出错?,c++,c++11,C++,C++11,在下面的(工作)代码示例中,模板化register_enum()函数用于迭代枚举,并调用用户提供的回调函数将枚举值转换为c字符串。所有枚举都是在一个类中定义的,枚举到字符串的转换是通过静态到字符串(enum)函数完成的。当一个类(如下面的着色器类)具有多个枚举并对应重载到_cstring(enum)函数时,编译器无法确定传递到register _enum()的正确的to _cstring()函数。我觉得代码解释得比我能解释的好 #include <functional> #inclu
#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;
}
#包括
#包括
//实际代码使用Lua,但为了简化
//我将在本例中隐藏它。
类型定义无效lua_状态;
类小部件
{
公众:
枚举类类型
{
开始=0,
窗口=开始,
按钮
纸卷
进步,
结束
};
静态常量字符*到字符串(常量类型值)
{
开关(值)
{
案例类型::窗口:返回“窗口”;
案例类型::按钮:返回“按钮”;
案例类型::滚动:返回“滚动”;
案例类型::进度:返回“进度”;
默认:中断;
}
返回空ptr;
}
};
类着色器
{
公众:
枚举类函数
{
开始=0,
翻译=开始,
旋转
规模
颜色
库德,
结束
};
枚举类波形
{
开始=0,
正弦=开始,
广场
三角形,
线性的
噪音
结束
};
静态常量字符*到字符串(常量函数值)
{
开关(值)
{
case FUNC::TRANSLATE:返回“TRANSLATE”;
case FUNC::ROTATE:返回“ROTATE”;
case FUNC::SCALE:返回“SCALE”;
case FUNC::COLOR:返回“COLOR”;
case FUNC::COORD:返回“COORD”;
默认:中断;
}
返回空ptr;
}
静态常量字符*到字符串(常量波形值)
{
开关(值)
{
案例波形::正弦:返回“正弦”;
案例波形::SQUARE:返回“SQUARE”;
案例波形::三角形:返回“三角形”;
案例波形::线性:返回“线性”;
案例波形::噪声:返回“噪声”;
默认:中断;
}
返回空ptr;
}
};
//递增枚举值。
//我的编译器(g++4.6)不支持枚举的类型_特征,因此
//这里我只是将枚举值强制转换为int。。。需要修理的东西
//后来。。。
模板
E和枚举增量(E和值)
{
返回值=(值==E::END)?E::BEGIN:E(静态_转换(值)+1);
}
widget::TYPE&operator++(widget::TYPE&e)
{
返回enum_increment(e);
}
着色器::FUNC&operator++(着色器::FUNC&e)
{
返回enum_increment(e);
}
着色器::波形和运算符++(着色器::波形和e)
{
返回enum_增量(e);
}
//向Lua注册枚举
模板
无效寄存器枚举(lua_State*L,const char*表名,std::functionto_cstring)
{
(void)L;//本例中未使用。
//实际代码在Lua中创建一个表,并将表[to_cstring(i)]=i设置为
对于(自动i=E::BEGIN;i std::cout错误告诉您有两种可能的重载可供使用,编译器无法为您做出决定。另一方面,您可以通过使用强制转换来确定使用哪种重载:
typedef const char *(*func_ptr)( shader::FUNC );
register_enum< shader::FUNC >( L, "functions", (func_ptr)shader::to_cstring );
typedef const char*(*func_ptr)(着色器::func);
将_enum(L,“functions”,(FUNC_ptr)shader::注册到_cstring);
或不带typedef(在较难阅读的单行中):
register\u enum(L,“函数”,
(const char*(*)(shader::FUNC))shader::to_cstring);
*请注意,在函数签名中,顶级的const
将被删除
下一个问题是编译器为什么没有自己找到合适的重载?问题是在调用register\u enum
时传递了枚举的类型,并确定std::function
的类型为std::function
,但是std::function
有一个模板构造函数,在试图推断构造函数的参数类型之前,编译器必须知道要使用哪个重载。我想说的是,在这种情况下,如果编译器无法在这两个重载之间做出决定,应该重命名其中一个!这将防止进一步的错误函数的用法不明确
typedef const char *(*func_ptr)( shader::FUNC );
register_enum< shader::FUNC >( L, "functions", (func_ptr)shader::to_cstring );
register_enum< shader::FUNC >( L, "functions",
(const char *(*)( shader::FUNC ))shader::to_cstring );