C11/C++11 宏,用于将常量字符串与文本整数相关联
C11/C++11 macro to associate a constant string to a literal integer
我已经有一大组C++源代码文件,其中包含对以这种方式编写的记录器函数的调用:
LogIx(_S("This is my msg"));
哪里:
#define _S(a) (#a)
它可以工作,但我的客户想在生产中放置一个不容易理解的记录器(我不太同意,但无论如何......源代码库非常大,所以我的想法是尽可能少地修改并将一个数字(索引)与每条消息相关联,并将所有消息放在一个表中,以便该数字将成为表中消息的索引。
第一个想法(有效)是找到所有_S(...)消息,从源中提取它们并用它们的等效项填充枚举,然后使用枚举标记更改每个_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;
}
任何想法或建议将不胜感激。
通过将文字转换为键入 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;
}
演示
相关文章:
- 如何在C++中用std::cout正确显示带十六进制的字符串文本
- 在编译时检查字符串文本的长度
- 读取字符串文本输入以创建 2D 矢量
- 管理字符串文本的最佳做法
- 定义宏以将前缀 0x 添加到十六进制字符串文本
- 无法在模板参数中定义字符串文本
- 不推荐使用 PTCHAR 的字符串文本
- C++ 字符串文本和常量
- C++20字符串文本模板参数工作示例
- 返回从字符串文本创建的静态string_view是否安全?
- 在处理任何字符大小的模板中使用字符串文本
- 是否保证相同内容字符串文本的存储相同?
- 将以 null 结尾的字节字符串转换为原始字符串文本
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 使用C++中的模板检测不同的字符串文本
- 无法完全专用化字符串文本的模板
- C++ - 确定 const char* 是指向字符串文本对象还是动态对象
- 是否可以在原始字符串文本中插入转义序列?
- C++带有捕获组的正则表达式字符串文本
- 为什么多维数组中的空字符串文本衰减为空指针?