对于可能被调用的T
中的每个f2<T>()
,如何强制在某个函数f1<T>
中调用所有f1_advanced()
推进?
class Manager(){
public: void f1_advanced (){ /* add code here */ }
private: template<class T> void f1 (){ }
public: template<class T> void f2 (){ }
}
class Usage{
void testCase(){
Manager manager;
manager.f1_advanced();
//^^ Must call f1<A> and f1<B> automatically.
// Whether it calls f1<C> or not, both cases are ok for me.
manager.f2<A>();
manager.f2<B>();
if(false) manager.f2<C>();
}
}
注意:A
,B
,...来自某个班级T0
。
我已搜索过,但找不到任何解决方案,不知道调用此功能的内容,甚至是否可行。
我只相信可以通过一些高级模板魔术来完成。
答案 0 :(得分:2)
有两条规则:
使用静态const bool,由静态注册函数初始化。
所有游戏必须以字符书写
这是我的妖精游戏
#include <unordered_map>
#include <vector>
#include <string>
#include <typeindex>
#include <iostream>
//
// base game object, suplpying polymorphic interface
struct GameObject
{
virtual void identify_thyself() const = 0;
GameObject() noexcept {}
GameObject(GameObject&&) noexcept = default;
GameObject(GameObject const&) noexcept = default;
GameObject& operator=(GameObject&&) noexcept = default;
GameObject& operator=(GameObject const&) noexcept = default;
virtual ~GameObject() = default;
};
// every game should be written in character, or you're not doing it right
template<class T>
struct ye {};
// an object manager which allows static registration of creation functions
struct Manager
{
using game_object_ptr = std::unique_ptr<GameObject>;
using create_object_function = std::function<game_object_ptr()>;
struct static_data
{
std::unordered_map<
std::type_index,
create_object_function
> creation_functions;
};
static static_data& get_static_data()
{
static static_data sd {};
return sd;
}
template<class T>
static void register_object(create_object_function creator) {
auto& statics = get_static_data();
// do whatever registration is required here
statics.creation_functions.emplace(typeid(T), std::move(creator));
}
template<class T>
static game_object_ptr create_monster(ye<T>)
{
// this will throw an exeption if the object wasn't registered
return get_static_data().creation_functions.at(typeid(T))();
}
};
// introducing: Ye Goblins!
struct Goblin : GameObject
{
Goblin(std::string name)
: _name(std::move(name))
{}
void identify_thyself() const override { std::cout << _name << " the goblin, waiting to a-slit your throat!\n"; }
static const bool registered;
std::string _name;
};
const bool Goblin::registered = [] {
Manager::register_object<Goblin>([]()->Manager::game_object_ptr{
static const std::vector<std::string> namez {
"Grunt",
"Basher",
"Pulveriser",
"Squisher"
};
static int iname = 0;
auto next_name = [&] {
auto s = namez[iname];
++iname;
if (iname >= namez.size()) iname = 0;
return s;
};
return std::make_unique<Goblin>(next_name());
});
return true;
}();
struct Hero : GameObject
{
void identify_thyself() const override { std::cout << "Harry the hero, waiting to degoblinise this blessed land!\n"; }
static const bool registered;
};
const bool Hero::registered = [] {
Manager::register_object<Hero>([]()->Manager::game_object_ptr{
return std::make_unique<Hero>();
});
return true;
}();
struct appear_verb {};
static constexpr appear_verb appear {};
static constexpr appear_verb appears {};
struct goblinator
{
auto operator,(appear_verb) const
{
std::vector<Manager::game_object_ptr> ye_hoard;
std::generate_n(std::back_inserter(ye_hoard), 4,
[] { return Manager::create_monster(ye<Goblin>()); } );
return ye_hoard;
}
};
static constexpr goblinator a_number_of_merry_goblins {};
struct heroinator
{
auto operator, (appear_verb) const
{
return Manager::create_monster(ye<Hero>());
}
};
static constexpr heroinator our_hero {};
struct identify_thyselfer
{
void operator, (const Manager::game_object_ptr& ptr) const {
ptr->identify_thyself();
}
};
static constexpr identify_thyselfer identify_thyself{};
struct identify_thyselvser
{
void operator, (std::vector<Manager::game_object_ptr> const& them) const
{
for (auto& yeself : them)
{
yeself->identify_thyself();
}
}
};
static constexpr identify_thyselvser identify_thyselves{};
struct methinkser
{
template<class T>
decltype(auto) operator, (T const& musings) const
{
return std::cout << musings << '\n';
}
};
static constexpr methinkser methinks {};
int main()
{
// Manager ye_manager; // not necessary since manager registration is static
methinks, "Introducing, the Goblins:";
auto ye_goblins = (a_number_of_merry_goblins, appear);
identify_thyselves, ye_goblins ;
methinks, "";
methinks, "Introducing, the Hero:";
auto ye_hero = (our_hero, appears);
identify_thyself, ye_hero;
}
玩这款引人入胜的游戏时的输出示例:
Introducing, the Goblins:
Grunt the goblin, waiting to a-slit your throat!
Basher the goblin, waiting to a-slit your throat!
Pulveriser the goblin, waiting to a-slit your throat!
Squisher the goblin, waiting to a-slit your throat!
Introducing, the Hero:
Harry the hero, waiting to degoblinise this blessed land!
答案 1 :(得分:0)
编译器无法知道Manager类的所有可能的类型扣除。你可以做的最好的事情就是编写一个包装器函数,该函数接收已经显式实例化的列表,并调用它们要测试的函数。