我的问题类似于这些,但似乎并没有完全相关:
我得到的是这样的:
struct thingy;
struct container
{
static container& instance(); // singleton
int register_thingy(thingy*);
};
struct thingy
{
virtual ~thingy() {}
virtual int id() const = 0;
};
//template trick to force registration.
template < typename Derived >
struct registered_thingy : thingy
{
registered_thingy() : my_id(my_static_id) {}
int id() const { return my_id; }
private:
int my_id;
static int my_static_id;
}
template < typename Derived >
int registered_thingy<Derived>::my_static_id =
container::instance().register_thingy(new Derived);
Run Code Online (Sandbox Code Playgroud)
现在,concrete_thingy.cpp我在一个文件中:
struct my_concrete_thingy : registered_thingy<my_concrete_thingy> …Run Code Online (Sandbox Code Playgroud) 我一直在我的代码中使用这个SO问题中描述的模式,制作各种编译时注册列表:编译时的C++类型注册技巧
例如,如果你有一堆lua回调函数,并且你不想忘记用一些lua状态注册它们,你可以使用一个宏来声明它们,这个宏将一个知道它们的名字和函数指针的模板类型放入一个列表中,然后你有一个记录所有功能的单行程.
这种技术的局限性(如SO答案中所述)是,如果n列表中有项目,则需要模板递归深度O(n)进行评估.这不太理想,我实际上已经有相当多的lua回调函数......
我曾经相信O(n)递归深度由于各种原因是不可避免的,但是正如我最近从Yakk那里学到的那样(未经证实的)答案,我天真地想到的一些基本的东西O(n)实际上可以O(log n)深入地完成.切换语句可变参数模板扩展
特别是,所涉及的数据结构不再需要O(log n)模板深度来进行操作.
我不确定的部分是Rank诀窍.从引用的代码,这个模板
template <int N>
struct Rank : Rank<N - 1> {};
template <>
struct Rank<0> {};
Run Code Online (Sandbox Code Playgroud)
是一个关键因素.虽然在模板深度方面很昂贵 - 实例化Rank<N>需要模板深度N.它具有的重要特性是,如果f定义了一个使用许多不同秩类型重载的函数,则重载决策总是选择最大排名的重载,因为这是"最派生的实例".例如,如果我们有这个代码:
bool f(Rank<0>) { return false; }
int f(Rank<1>) { return 0; }
float f(Rank<2>) { return 0; }
double f(Rank<3>) { return 0; }
Run Code Online (Sandbox Code Playgroud)
那么在代码中的任何一点,decltype(f(Rank<100>{}))类型都等于最近定义的重载的返回值.即这些断言通过
bool f(Rank<0>) { return false; …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个在运行时动态加载其扩展的应用程序.我使用Boost预处理器库来编写预处理器函数,给定一个名称列表,为每个名称声明一个类(并使所有这些类成为某些AbstractPlugin类的子类),然后声明包含这些类的Boost MPL序列.然后我编写了一个类,它尝试指向AbstractPlugin,如果它可以转换为该MPL序列中的任何类型.这里的问题是我的预处理器功能需要我想要创建和加载的所有扩展的完整列表.是否有一些技术可以让我在一个单独的文件中注册每个扩展名?
更新:
我相信,我对情况的解释太模糊了,所以我决定让它更具体.
我想定义一个扩展类型的集合.对于每种扩展类型,可以有任意数量的扩展名.在运行期间,程序加载外部库,解析入口点函数,调用它,结果得到一个指针.然后它尝试将该指针强制转换为所有已注册的扩展类型(使用dynamic_cast,因此扩展类型的类都从某些多态基类继承).如果对某个扩展类型的强制转换成功,则在对该扩展类型的特殊处理程序的调用中使用已转换的指针.
扩展类型的数量在编译时是已知的(显然,扩展的数量是无限的).使用我的aproach,loader类使用这些知识来检查是否存在每个扩展类型的处理程序(如果没有,程序不编译).另外,我的aproach不强制扩展类型的类知道有关加载器的任何信息(因此很容易修改加载器).但是如果每个扩展类型都注册自己会更方便.
所以我想假设我有以下类定义:
class my_named_int {
public:
int value;
const string name;
my_named_int(int _value, /*...Does Something Go Here...?*/);
};
Run Code Online (Sandbox Code Playgroud)
我想要的是,如果我写下面的代码:
int main() {
my_named_int my_name(5);
std::cout << my_name.name << ":" << my_name.value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我希望输出为:
my_name:5
Run Code Online (Sandbox Code Playgroud)
显然,解决这个问题的最简单方法是编写如下代码:
class my_named_int {
public:
int value;
const string name;
my_named_int(int _value, const string & _name);
};
int main() {
my_named_int my_name(5, "my_name");
std::cout << my_name.name << ":" << my_name.value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是,当然,这会增加我的代码的重复性.有没有办法在没有变量名称的"双重写入"的情况下在C++中执行此操作,如果是这样,我将如何处理它?