构造使用字符串定义名称

Constructing define names using strings

本文关键字:定义 字符串      更新时间:2023-10-16

我得到了一些我想使用的常量int值,所以我使用了 #define。

问题是我得到了一些这样的定义名称:

#define a1  123
#define a2  6543
#define a3  12
...

代码中有没有办法以某种方式迭代它们以使用字符串构造它们的名称,然后获取该构造字符串的定义值?我的意思的伪代码:

for(int i =0 ; i < 100; i++)
{
string name = "a" + i;
func(GetDefineName(name)); // should call here every time to func with a1,a2 etc.
}

我习惯了 C#,所以我在习惯 c++ 时遇到了一些问题。定义真的是最合适的方法吗?

#开头的行由预处理器计算 - 编译器不会看到它们,只会看到它们的效果。因此,C++代码不能与预处理器变量交互,因为在编译代码时它们不再存在。

常量可以这样定义,但C++提供了更好的方法。例如,它们可以包装在命名空间中以避免名称冲突。

//auto lets the compiler deduce the type for you
auto const my_var = 4.5; //double
auto const close_to_pi = 3.4f; //float
auto const the_answer = 42; //int
auto const kibibyte = 1024u; //unsigned int

若要获取有关定义后缀的类型的更多说明,请查看整数文本和浮点文本。您可能还想稍后阅读 constexpr,当您更熟悉C++来探索编译时常量表达式时。

代码中有没有办法以某种方式迭代它们以使用字符串构造它们的名称,然后获取该构造字符串的定义值?

不,没有办法使用定义来做到这一点。

您需要将值放入某个容器中才能迭代这些值。

如果你只想存储值,你可以使用 std::vector。

如果你想要同时拥有名称和值,你可以使用 std::map。像这样:

#include <iostream>
#include <string>
#include <map>
#define a0 42
#define a1 5
#define a2 15
#define a3 25
int main() {
// Define the map
std::map<std::string, int> m;
// Intialize the map
m["a0"] = a0;
m["a1"] = a1;
m["a2"] = a2;
m["a3"] = a3;
// Access map using name
for(size_t i =0 ; i < m.size(); i++)
{
std::string name = "a" + std::to_string(i);
std::cout << m[name] << std::endl;
}
// Iterate all map elements
for (auto& x : m)
{
std::cout << x.first << ":" << x.second << std::endl;
}
return 0;
}

另一种方法是生成一些包含所需内容的C++文件。因此,您需要为此目的设置构建。你经常使用一些构建自动化工具(如GNU make,ninja等(,你可以配置它在需要时生成一些C++文件(例如,如果你使用make,则在Makefile中添加几行(。生成一些C++代码的程序可以是一些脚本(例如shell,awk,Python,Guile等(,一些专门的元程序(例如Qt程序的moc(,其他一些预处理器,如GPP或m4,或您自己的其他C++程序等。自上个世纪以来,这种元编程方法通常与C++和C一起使用(看看Qt moc,bison,SWIG,...例如(。

另请参阅对相关问题的回答(带 C(。

你会生成一些包含以下内容的标题

#define a1  123
#define a2  6543
#define a3  12

(你不想在这样的#define-s 中=(

或者你可能会生成一些enum,比如

enum number_en {
a1= 123,
a2= 6543,
a3= 12,
};

请注意,在运行时生成C++代码可能比其他解决方案更有效(自构建时以来((例如std::map基于(方法。

宏由预处理器解析,处理器不知道(不能在代码中使用它们(。

如果要将名称与值相关联,可以使用 const map 和 constexpr 表达式:

constexpr std::string a1="a1";
constexpr std::string a2="a2";
constexpr std::string a3="a3";
const std::map<std::string, int> = {
{a1, 123},
{a2, 6543},
{a3, 12} 
}

您需要 C++11(或更高版本(才能正常工作。

更喜欢常量变量而不是宏

constexpr auto a1 = 123;
constexpr auto a2 = 6543;
constexpr auto a3 = 12;

然后迭代它们,不需要名称,只需执行

for (auto e : {a1, a2, a3}) {
func(e);
}

您可能希望为列表创建一个变量,以避免在多个位置迭代时重复。