编译时元编程,使用字符串文字

发布于 2024-08-28 18:20:05 字数 1064 浏览 7 评论 0原文

我正在编写一些代码,这些代码确实可以用于一些简单的编译时元编程。使用空结构标记作为编译时符号是常见的做法。我需要用一些运行时配置元素来装饰标签。静态变量似乎是唯一的方法(启用元编程),但是静态变量需要全局声明。为了回避 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

像极了他 2024-09-04 18:20:05

我终于明白了问题所在......并且您的解决方案并没有解决太多问题(如果有的话)。

使用局部静态变量的目标是在首次使用时提供初始化,从而避免“初始化顺序失败”(顺便说一句,它不能解决“销毁顺序失败”)。

但是根据您的设计,如果您有效地防止了崩溃,那么您并不能防止在使用变量值之前使用变量的问题。

ImportantObject<tbt> SinceSliceBread; // using an empty string

tbt::set_name("xyz");

与以下使用进行比较:

std::string& tbt::get_name() { static std::string MName = "xyz"; return MName; }

这里,名称不仅被创建,而且在第一次使用时初始化。使用未初始化的名称有什么意义?

好吧,现在我们知道你的解决方案不起作用,让我们想一下。事实上,我们希望自动执行此操作:(

struct tag
{
  static const std::string& get_name();
  static const std::string& get_fs_location();
};

可能需要一些访问器来修改它们)

我的第一个(也是简单的)解决方案是使用宏(bouh 不是类型安全的):

#define DEFINE_NEW_TAG(Tag_, Name_, FsLocation_)              \
  struct Tag_                                                 \
  {                                                           \
    static const std::string& get_name() {                    \
      static const std::string name = #Name_;                 \
      return name;                                            \
    }                                                         \
    static const std::string& get_fs_location() {             \
      static const std::string fs_location = #FsLocation_;    \
      return fs_location;                                     \
    }                                                         \
  };

在您的情况下,另一个解决方案可能是使用 < 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.

ImportantObject<tbt> SinceSliceBread; // using an empty string

tbt::set_name("xyz");

Compare with the following use:

std::string& tbt::get_name() { static std::string MName = "xyz"; return MName; }

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:

struct tag
{
  static const std::string& get_name();
  static const std::string& get_fs_location();
};

(with possibly some accessors to modify them)

My first (and easy) solution would be to use a macro (bouh not typesafe):

#define DEFINE_NEW_TAG(Tag_, Name_, FsLocation_)              \
  struct Tag_                                                 \
  {                                                           \
    static const std::string& get_name() {                    \
      static const std::string name = #Name_;                 \
      return name;                                            \
    }                                                         \
    static const std::string& get_fs_location() {             \
      static const std::string fs_location = #FsLocation_;    \
      return fs_location;                                     \
    }                                                         \
  };

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文