#include <memory>
#include <iostream>
#include <string>
#include <map>
#include <array>
using namespace std;
struct GameState{
virtual string info() const = 0;
};
string GameState::info() const{
return "GameState.info: ";
}
typedef shared_ptr<GameState> state_ptr;
struct MenuState : GameState{
string info() const{ return GameState::info() + "Menu"; }
};
struct PlayState : GameState{
string info() const{ return GameState::info() + "Play"; }
};
template<class T>
state_ptr create(){ return shared_ptr<GameState>(new T()); }
typedef state_ptr (*create_fptr)();
class Manager{
private:
state_ptr m_state;
public:
state_ptr state(){ return m_state; }
state_ptr state(string name){
static map<string, create_fptr> create_funcs = {
{{"Menu"}, {create<MenuState>}},
{{"Play"}, {create<PlayState>}}
};
return m_state = create_funcs[name]();
}
state_ptr state(state_ptr state){
return m_state = state;
}
};
int main(){
Manager m;
array<string, 2> names =
{ "Menu", "Play" };
array<state_ptr, 2> objects =
{ create<PlayState>(), create<MenuState>() };
for(auto name : names)
cout << m.state(name)->info() << endl;
for(auto object : objects)
cout << m.state(object)->info() << endl;
return 0;
}
I2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8YXJyYXk+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgpzdHJ1Y3QgR2FtZVN0YXRlewoJdmlydHVhbCBzdHJpbmcgaW5mbygpIGNvbnN0ID0gMDsKfTsKc3RyaW5nIEdhbWVTdGF0ZTo6aW5mbygpIGNvbnN0ewoJcmV0dXJuICJHYW1lU3RhdGUuaW5mbzogIjsKfQp0eXBlZGVmIHNoYXJlZF9wdHI8R2FtZVN0YXRlPiBzdGF0ZV9wdHI7CgpzdHJ1Y3QgTWVudVN0YXRlIDogR2FtZVN0YXRlewoJc3RyaW5nIGluZm8oKSBjb25zdHsgcmV0dXJuIEdhbWVTdGF0ZTo6aW5mbygpICsgIk1lbnUiOyB9Cn07CgpzdHJ1Y3QgUGxheVN0YXRlIDogR2FtZVN0YXRlewoJc3RyaW5nIGluZm8oKSBjb25zdHsgcmV0dXJuIEdhbWVTdGF0ZTo6aW5mbygpICsgIlBsYXkiOyB9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPgpzdGF0ZV9wdHIgY3JlYXRlKCl7IHJldHVybiBzaGFyZWRfcHRyPEdhbWVTdGF0ZT4obmV3IFQoKSk7IH0KdHlwZWRlZiBzdGF0ZV9wdHIgKCpjcmVhdGVfZnB0cikoKTsKCmNsYXNzIE1hbmFnZXJ7CnByaXZhdGU6CglzdGF0ZV9wdHIgbV9zdGF0ZTsKcHVibGljOgoJc3RhdGVfcHRyIHN0YXRlKCl7IHJldHVybiBtX3N0YXRlOyB9CglzdGF0ZV9wdHIgc3RhdGUoc3RyaW5nIG5hbWUpewoJCXN0YXRpYyBtYXA8c3RyaW5nLCBjcmVhdGVfZnB0cj4gY3JlYXRlX2Z1bmNzID0gewoJCQl7eyJNZW51In0sIHtjcmVhdGU8TWVudVN0YXRlPn19LAoJCQl7eyJQbGF5In0sIHtjcmVhdGU8UGxheVN0YXRlPn19CgkJfTsKCQlyZXR1cm4gbV9zdGF0ZSA9IGNyZWF0ZV9mdW5jc1tuYW1lXSgpOwoJCQoJfQoJc3RhdGVfcHRyIHN0YXRlKHN0YXRlX3B0ciBzdGF0ZSl7CgkJcmV0dXJuIG1fc3RhdGUgPSBzdGF0ZTsKCX0KfTsKCmludCBtYWluKCl7CglNYW5hZ2VyIG07CgkKCWFycmF5PHN0cmluZywgMj4gbmFtZXMgPSAKCQl7ICJNZW51IiwgIlBsYXkiIH07CglhcnJheTxzdGF0ZV9wdHIsIDI+IG9iamVjdHMgPSAKCQl7IGNyZWF0ZTxQbGF5U3RhdGU+KCksIGNyZWF0ZTxNZW51U3RhdGU+KCkgfTsKCQkKCWZvcihhdXRvIG5hbWUgOiBuYW1lcykKCQljb3V0IDw8IG0uc3RhdGUobmFtZSktPmluZm8oKSA8PCBlbmRsOwoJZm9yKGF1dG8gb2JqZWN0IDogb2JqZWN0cykKCQljb3V0IDw8IG0uc3RhdGUob2JqZWN0KS0+aW5mbygpIDw8IGVuZGw7CgkJCglyZXR1cm4gMDsKfQ==