2016-03-21 64 views
0

我已經有一個大的一套包含寫在這樣一個記錄器功能調用C++源代碼文件:C11/C++ 11宏常量字符串關聯到面值整數

LogIx(_S("This is my msg")); 

其中:

#define _S(a) (#a) 

它的工作原理,但我的客戶希望把在生產中不記錄器易於理解(我不同意這麼多,但無論如何...)。源代碼基數非常大,所以我的想法是儘可能少地修改它,並將一個數字(索引)與每個消息相關聯,並將所有消息放入一個表中,以使該數字成爲表中消息的索引。

第一個想法是找到所有_S(...)消息,從源代碼中提取它們,並用它們的等價物填充枚舉,然後使用枚舉標記更改每個_S()內部的參數。當然,這並不容易出錯,並且在將來添加其他消息的想法也不是很好。

所以我想使用preprocesor的不同解決方案,但似乎不可能在#define中使用帶引號的字符串。

這一塊的C++源代碼不工作,但顯示我想要做什麼:

#define _V(a) (#a) 

const std::array<string, 3> s_logStrings = { 
     _V("This is my msg"), 
     _V("Param %s is: %d"), 
     _V("Reset msg") 
}; 

#define _S("This is my msg") 0 
#define _S("Param %s is: %d") 1 
#define _S("Reset msg")  2 

int Log(size_t msgIndex) 
{ 
    cout << s_logStrings.at(LogIx(msgIndex)); 
} 

int main(void) 
{ 
    std::cout << "Begin test" << std::endl; 
    Log(_S("This is my msg")); 
    std::cout << "End test" << std::endl; 

    return 0; 
} 

#define _V(a) (#a) 

const std::array<string, 3> s_logStrings = { 
     _V("This is my msg"), 
     _V("Param %s is: %d"), 
     _V("Reset msg") 
}; 

#define _S(a) // ???? this is the problem... how define this macro? 
// also a constexpr could be a good solution, the point is to don't 
// add a function or a <map> 

#define _S("This is my msg") 0 
#define _S("Param %s is: %d") 1 
#define _S("Reset msg")  2 

int Log(size_t msgIndex) 
{ 
    cout << s_logStrings.at(msgIndex); 
} 

int main(void) 
{ 
    std::cout << "Begin test" << std::endl; 
    Log(_S("This is my msg")); 
    std::cout << "End test" << std::endl; 

    return 0; 
} 

的任何意見或建議將不勝感激。

+1

注意,以下劃線跟着一個大寫字母('_S'並開始'名字_V'),並且包含兩個連續下劃線的名稱保留給實現。不要使用它們。 –

回答

0

通過轉動你的文字輸入爲char_sequence, 你可以這樣做:

template <char ... > struct char_sequence {}; 

// use gnu extension :/ 
template<class CharT, CharT... cs> 
char_sequence<cs...> operator ""_seq(){ 
    return {}; 
} 

template <class T, class Tuple> 
struct index_in_tuple; 

template <class T, class... Types> 
struct index_in_tuple<T, std::tuple<T, Types...>> { 
    static const std::size_t value = 0; 
}; 

template <class T, class U, class... Types> 
struct index_in_tuple<T, std::tuple<U, Types...>> { 
    static const std::size_t value = 1 + index_in_tuple<T, std::tuple<Types...>>::value; 
}; 

using MyMessagesTuple = decltype(std::make_tuple(
    "This is my msg"_seq, 
    "Param %s is: %d"_seq, 
    "Reset msg"_seq 
)); 


#define _S(a) (index_in_tuple<decltype(a##_seq), MyMessagesTuple>::value) 

int main() { 
    auto foo = _S("Reset msg"); 
    std::cout << foo << std::endl; 
} 

Demo