C11/C++;11宏将常量字符串与文字整数相关联 我已经有一个大的C++源代码集,其中包含用这种方式写的记录器函数的调用: LogIx(_S("This is my msg"));
其中:C11/C++;11宏将常量字符串与文字整数相关联 我已经有一个大的C++源代码集,其中包含用这种方式写的记录器函数的调用: LogIx(_S("This is my msg"));,c++,string,c++11,enums,C++,String,C++11,Enums,其中: #define _S(a) (#a) 它可以工作,但我的客户希望在生产中使用一个不容易理解的记录器(我不太同意,但无论如何…)。源代码库非常大,因此我的想法是尽可能少地修改,并将一个数字(索引)与每条消息关联,并将所有消息放在一个表中,以便该数字将成为表中消息的索引 第一个想法(有效)是找到所有的_S(…)消息,从源中提取它们,并用它们的等价物填充一个枚举,然后用enum标记更改每个_S()中的参数。当然,将来添加其他消息并不容易出错,也不是很好的想法 因此,我正在考虑使用预处理器的
#define _S(a) (#a)
它可以工作,但我的客户希望在生产中使用一个不容易理解的记录器(我不太同意,但无论如何…)。源代码库非常大,因此我的想法是尽可能少地修改,并将一个数字(索引)与每条消息关联,并将所有消息放在一个表中,以便该数字将成为表中消息的索引
第一个想法(有效)是找到所有的_S(…)消息,从源中提取它们,并用它们的等价物填充一个枚举,然后用enum标记更改每个_S()中的参数。当然,将来添加其他消息并不容易出错,也不是很好的想法
因此,我正在考虑使用预处理器的另一种解决方案,但似乎不可能在#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;
}
定义V(a)(a)
常量std::数组s_日志字符串={
_V(“这是我的味精”),
_V(“参数%s为:%d”),
_V(“重置消息”)
};
#定义_S(“这是我的消息”)0
#定义(参数%S为:%d)1
#定义(“重置消息”)2
整数日志(大小\u t msgIndex)
{
通过将文本转换为字符序列,可以, 你可以这样做:
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;
}
模板结构字符序列{};
//使用gnu扩展:/
模板
字符序列运算符“”\u seq(){
返回{};
}
模板
元组中的结构索引;
模板
元组中的结构索引{
静态常数std::size\u t值=0;
};
模板
元组中的结构索引{
静态常量std::size\u t value=1+元组中的索引\u::value;
};
使用MyMessagesTuple=decltype(std::make_tuple)(
“这是我的味精”\u seq,
“参数%s为:%d”\u seq,
“重置消息”_seq
));
#定义_S(a)(在_tuple::value中索引_)
int main(){
自动foo=_S(“重置消息”);
std::请注意,以下划线开头,后跟大写字母(\u S
和\u V
)的名称以及包含两个连续下划线的名称将保留给实现。不要使用它们。