私は移行テーブル実行時にロードされたステートマシンを書いてきたクラスのメンバ関数への文字列のマップへのスマートポインタを格納して、不完全な型のために失敗しないようにする方法?
背景。各遷移にかかるアクションは文字列として格納されます。文字列は、ステートマシンクラスのメンバ関数を指すstd::function
オブジェクトに変換されます。イベントが発生し、遷移すると、その関数が呼び出されます。
問題
実行時に呼び出される関数を決定する前に、私はこの戦略を成功裏に使用されています。残念ながら、私は次のようなエラーに実行してきた:
-
を撮影
GoogleとStackoverflowに相談しました。私はタイプが不完全な場所から定義を取り出すことを含む多くのアイデアを得ました。残念ながら、私は正常に動作するようにはできませんでした。
unique_ptr
の代わりに未加工のポインタを使用してみましたが、魔法のように動作することがわかりました。私は不完全な型を扱う方法
shared_ptr
とunique_ptr
との差に少し読んでしまいました。私はshared_ptrを試しましたが、それは私の問題を解決しませんでした。フレンドクラスの宣言の時までに、タイプが全体と見なされることを願って、
friend
クラスを自分のステートマシンに作成しようとしました。私はこれを働かせることができませんでした。最後に、次の最小限の例(エラーを再現するコードのコメントを外してください)を作成しました。これは、問題が発生したことを示しています。http://coliru.stacked-crooked.com/a/791092c7ca8fff24となりました。 :)
error: return type 'XStMachine::TrFunc {aka class std::function<void (XStMachine::*)(const EventData&)>}' is incomplete
それとも
invalid use of incomplete type
手順
ソースコード
#include <iostream>
#include <string>
#include <functional>
#include <memory>
#include <map>
#include <iomanip>
using namespace std;
struct EventData
{
unsigned int x;
};
class Friendly; // Required for compiling the code. Why?
class XStMachine
{
friend class Friendly;
unique_ptr<Friendly> fPtr; //-- Doesn't compile if Friendly is not fwd. declared
unsigned int y;
unsigned int z;
public:
typedef void(XStMachine::*TrFuncPtr)(EventData const&);
typedef std::function<TrFuncPtr> TrFunc;
private:
// map<string, TrFunc> fMap; //-- Doesn't compile because TrFunc is incomplete
// unique_ptr<map<string, TrFunc>> fMap; // Doesn't compile; incomplete type.
map<string, TrFunc> *fMap; // Compiles with incomplete type.
protected:
void tranFunc1(EventData const &d)
{
y = d.x;
}
void tranFunc2(EventData const &d)
{
z = d.x;
}
public:
XStMachine()
{
// Code to init fMap
}
// The code below doesn't compile. incomplete type.
TrFunc getTranFunc(std::string const &s)
{
return (*fMap)[s];
}
~XStMachine()
{
}
};
class Friendly
{
// unique_ptr<map<string, XStMachine::TrFunc> fMap; // Doesn't compile, the type is incomplete.
public:
Friendly()
{
// Code to allocate and init fMap
}
// Dosen't compile if defined here because the return type is incomplete.
//XStMachine::TrFunc& getTranFunc(std::string const&)
//{
// return (*fMap)[s];
//}
};
// The type is incomplete -> Will this work inside a separate cpp file?
//XStMachine::TrFunc& getTranFunc(std::string const &s)
//{
// Weird - Can't access protected members though we're friends. :/
/*
static map<string, XStMachine::TrFunc> fMap = {{"tranFunc1", function(&XStMachine::tranFunc1)},
{"tranFunc2", function(&XStMachine::tranFunc2)}
};
*/
//return fMap[s];
//}
int main() {
cout << "I need to understand incomplete types." << endl;
return 0;
}
Coliru(GCC 6からフル・エラー出力。3、C++ 14)
main.cpp: In member function 'XStMachine::TrFunc XStMachine::getTranFunc(const string&)':
main.cpp:48:3: error: return type 'XStMachine::TrFunc {aka class std::function<void (XStMachine::*)(const EventData&)>}' is incomplete
{
^
In file included from /usr/local/include/c++/6.3.0/bits/stl_algobase.h:64:0,
from /usr/local/include/c++/6.3.0/bits/char_traits.h:39,
from /usr/local/include/c++/6.3.0/ios:40,
from /usr/local/include/c++/6.3.0/ostream:38,
from /usr/local/include/c++/6.3.0/iostream:39,
from main.cpp:1:
/usr/local/include/c++/6.3.0/bits/stl_pair.h: In instantiation of 'struct std::pair<const std::__cxx11::basic_string<char>, std::function<void (XStMachine::*)(const EventData&)> >':
/usr/local/include/c++/6.3.0/bits/stl_map.h:481:10: required from 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::function<void (XStMachine::*)(const EventData&)>; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::function<void (XStMachine::*)(const EventData&)> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::function<void (XStMachine::*)(const EventData&)>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]'
main.cpp:49:23: required from here
/usr/local/include/c++/6.3.0/bits/stl_pair.h:196:11: error: 'std::pair<_T1, _T2>::second' has incomplete type
_T2 second; /// @c second is a copy of the second object
^~~~~~
In file included from main.cpp:3:0:
/usr/local/include/c++/6.3.0/functional:1526:11: note: declaration of 'class std::function<void (XStMachine::*)(const EventData&)>'
class function;
^~~~~~~~
目的
プライマリ:サンプルコードで何が起こっているのかを理解し、それを修正します。
セカンダリ:不完全なタイプが何であるかを明確に把握して、できること: *将来的に関連する問題を解決してください。 * unique_ptrのデフォルトのDeleterを、デフォルトを呼び出すDeleterでオーバーライドすることが安全かどうかを確認します。
私の理解の欠如は本当に私のここに来ています。
関連の質問
Friendly
は、サンプルコードではXStMachine
内のフレンドとして宣言されていても、それは前方だけでなく、以前のプログラムで宣言する必要があります。なぜこれが起こるのですか?Friendly
が友人と宣言されていても、保護されたメンバー関数XStMachine
にアクセスすることはできません。たとえば、&XStMachine::tranFunc1
は無効です。どうして?
質問全体にエラー*が発生するコードとともに、*完全なエラー出力(可能性のある情報メモを含む)が必要であることを知るには、十分な経験が必要です。 –
問題のエラーを引き起こすコードは、私の質問の[本文にリンクされています](http://coliru.stacked-crooked.com/a/791092c7ca8fff24)で十分でない理由がありますか?私はもっと詳細なエラー出力を共有しますが、私は本当に多くをカットしていません。念押し有難う。 – batbrat
@batbrat _ "それは十分ではない何らかの理由がありますか?" _はい、あなたの質問は自己完結型である必要があります。コードが長すぎる場合は、エラーを再現する[MCVE]に絞り込みます。 –