2010-04-16 75 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