编译时元编程,使用字符串文字
我正在编写一些代码,这些代码确实可以用于一些简单的编译时元编程。使用空结构标记作为编译时符号是常见的做法。我需要用一些运行时配置元素来装饰标签。静态变量似乎是唯一的方法(启用元编程),但是静态变量需要全局声明。为了回避 Scott Myers 的建议(来自《Effective C++》第三版),我想到了通过在函数内部声明静态变量而不是类变量来对静态变量的初始化进行排序。
所以我想出了下面的代码,我的假设是它会让我有一个编译时符号,其中的字符串文字可以在运行时使用。我没有错过任何我希望的东西,并且只要我在初始化依赖的模板类之前填充运行时字段,这就会正常工作? 。
#include <string>
template<class Instance>
class TheBestThing {
public:
static void set_name(const char * name_in) {
get_name() = std::string(name_in);
}
static void set_fs_location(const char * fs_location_in) {
get_fs_location() = std::string(fs_location_in);
}
static std::string & get_fs_location() {
static std::string fs_location;
return fs_location;
}
static std::string & get_name() {
static std::string name;
return name;
}
};
struct tag {};
typedef TheBestThing<tag> tbt;
int main()
{
tbt::set_name("xyz");
tbt::set_fs_location("/etc/lala");
ImportantObject<tbt> SinceSlicedBread;
}
编辑: 创建了社区维基。
I'm writing some code which could really do with some simple compile time metaprogramming. It is common practise to use empty-struct tags as compile time symbols. I need to decorate the tags with some run-time config elements. static variables seem the only way to go (to enable meta-programming), however static variables require global declarations. to side step this Scott Myers suggestion (from the third edition of Effective C++), about sequencing the initialization of static variables by declaring them inside a function instead of as class variables, came to mind.
So I came up with the following code, my hypothesis is that it will let me have a compile-time symbol with string literals use-able at runtime. I'm not missing anything I hope, and that this will work correctly, as long as I populate the runtime fields before I Initialize the depending templates classes ? .
#include <string>
template<class Instance>
class TheBestThing {
public:
static void set_name(const char * name_in) {
get_name() = std::string(name_in);
}
static void set_fs_location(const char * fs_location_in) {
get_fs_location() = std::string(fs_location_in);
}
static std::string & get_fs_location() {
static std::string fs_location;
return fs_location;
}
static std::string & get_name() {
static std::string name;
return name;
}
};
struct tag {};
typedef TheBestThing<tag> tbt;
int main()
{
tbt::set_name("xyz");
tbt::set_fs_location("/etc/lala");
ImportantObject<tbt> SinceSlicedBread;
}
edit:
Made community wiki.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我终于明白了问题所在......并且您的解决方案并没有解决太多问题(如果有的话)。
使用局部静态变量的目标是在首次使用时提供初始化,从而避免“初始化顺序失败”(顺便说一句,它不能解决“销毁顺序失败”)。
但是根据您的设计,如果您有效地防止了崩溃,那么您并不能防止在使用变量值之前使用变量的问题。
与以下使用进行比较:
这里,
名称
不仅被创建,而且在第一次使用时初始化。使用未初始化的名称有什么意义?好吧,现在我们知道你的解决方案不起作用,让我们想一下。事实上,我们希望自动执行此操作:(
可能需要一些访问器来修改它们)
我的第一个(也是简单的)解决方案是使用宏(bouh 不是类型安全的):
在您的情况下,另一个解决方案可能是使用 < code>boost::optional 来检测该值尚未初始化,并推迟依赖于它的值的初始化。
I've finally understood what the problem was... and your solution does not solve much, if any.
The goal of using local static variable is to provide initialization on first use, thus being safe from the "Initialization Order Fiasco" (by the way, it does not solve the "Destruction Order Fiasco").
But with your design, if you effectively prevent the
crash
you do not however prevent the issue of using a variable before its value is used.Compare with the following use:
Here the
name
is not only created but also initialized on first use. What's the point of using a non initialized name ?Well, now that we know your solution does not work, let's think a bit. In fact we would like to automate this:
(with possibly some accessors to modify them)
My first (and easy) solution would be to use a macro (bouh not typesafe):
The other solution, in your case, could be to use
boost::optional
to detect that the value has not been initialized yet, and postpone initialization of the values that depend on it.