[解決済み] std::functionを使用する際に発生する<unresolved overloaded function type>エラーを解決するにはどうすればよいですか?
質問
次のコード例では、テンプレート化された register_enum() 関数を使用して、列挙を繰り返し、ユーザーが提供するコールバックを呼び出して列挙値を c-文字列に変換しています。すべての列挙はクラス内で定義され、列挙値から文字列への変換は静的な to_cstring( enum ) 関数で行われます。クラス(下のシェーダクラスのような)が複数の列挙とそれに対応するオーバーロードされた to_cstring( enum ) 関数を持つ場合、コンパイラは register_enum() に渡すべき正しい to_cstring() 関数がどれかを決定できないのです。コードの方がうまく説明できると思うのですが...。
#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)>)
register_enum() に正しい to_cstring 関数を渡すにはどうしたらよいですか? 個々の to_cstring() 関数の名前を変更することができるのは承知していますが、可能であればこれは避けたいと考えています。おそらく私のデザインは胡散臭いので、より良いアプローチをお勧めします。
私の質問は、次のようなものです。 テンプレートを使用したオーバーロード関数の呼び出し(未解決のオーバーロード関数型コンパイラーエラー) と オーバーロードされたメンバ関数のアドレスを取得する方法は? が、今のところ、その情報を私の特定の問題に適用することはできません。
解決するには?
このエラーは、使用可能なオーバーロードが2つあり、コンパイラが判断できないことを告げています。一方、キャストを使用すれば、どちらを使用するかを決定することができます。
typedef const char *(*func_ptr)( shader::FUNC );
register_enum< shader::FUNC >( L, "functions", (func_ptr)shader::to_cstring );
あるいは、typedefなし(読みにくいワンライナーで)。
register_enum< shader::FUNC >( L, "functions",
(const char *(*)( shader::FUNC ))shader::to_cstring );
*
関数シグネチャでは、トップレベルの
const
は削除されます。
次の疑問は、なぜコンパイラは適切なオーバーロードを自分で見つけられなかったのでしょうか?そこで問題となるのは
register_enum
の型は、enum の型を渡すことによって決定されます。
std::function
になります。
std::function< const char* ( shader::FUNC ) >
しかし
std::function
はテンプレート化されたコンストラクタを持っており、コンストラクタの引数の型を推測しようとする前に、コンパイラはどのオーバーロードを使用したいかを知る必要があります。
関連
-
[解決済み] テスト
-
[解決済み】coutはstdのメンバではない
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] 配列のベクトルを扱う正しい方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件