2010-04-16 76 views
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; 
} 

编辑: 制造社会的维基。

+1

@Hassan:我注意到刚才。但是,仍然可以使用更好的标签:)虽然收回。 – 2010-04-16 10:38:47

+0

这些标签完全适用于任何寻找此特定问题的人。 – 2010-04-16 10:39:54

+1

但问题是什么? – 2010-04-16 10:43:52

回答

1

我终于明白了问题所在......而且如果有的话,您的解决方案并不能解决太多问题。

使用本地静态变量的目标是在首次使用时提供初始化,因此可以从“初始化命令Fiasco”(顺便说一句,它不解决“销毁命令Fiasco”)中安全。

但随着你的设计,如果你有效防止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检测到该值尚未初始化,并推迟依赖于它的值初始化。

+0

是的,我没有解决初始化排序问题,我主要关心的是有一个简单的方法来使用在编译时可用的字符串,并将它们与编译时间标记相关联。 Boost :: MPI字符串文字是一个黑客和C++ 0x解决这个问题。所以,我从Myers的书中选择了静态字符串声明的功能。感谢你的分析,你的宏可以使代码更像一个故事。 – 2010-04-16 12:13:48

+0

接受为答案,因为它增加了问题的价值。但是,很多人讨论过这个问题,并且我已经对问题中的代码进行了连续编辑。增强可选是防范初始化问题的一种非常好的方法。也许我会添加它,但是因为代码是供我的项目内部使用的,所以我可能不会马上这样做。 – 2010-04-18 23:28:05