1

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

编辑: 制作社区维基。

4

1 回答 1

1

我终于明白问题出在哪里了……如果有的话,您的解决方案并不能解决太多问题。

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

但是在您的设计中,如果您有效地阻止了,那么crash您不会阻止在使用变量值之前使用变量的问题。

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

tbt::set_name("xyz");

与以下用途进行比较:

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

这里name不仅是创建的,而且在首次使用时初始化。使用非初始化名称有什么意义?

好吧,既然我们知道您的解决方案不起作用,让我们考虑一下。事实上,我们想自动化这个:

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

(可能有一些访问者来修改它们)

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

#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;                                     \
    }                                                         \
  };

在您的情况下,另一种解决方案可能是用于boost::optional检测该值尚未初始化,并推迟初始化依赖于它的值。

于 2010-04-16T11:51:20.663 回答