Reputation: 12434
I got some constant int
values I would like to use, So I used #define.
The issue is that I got some define names like this:
#define a1 123
#define a2 6543
#define a3 12
...
Is there a way in the code to somehow iterate over them to construct their name with strings and then get the define value of that constructed strings? A pseudo code of what I mean:
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.
}
I'm used to C# so I got some problems getting used to c++. Is define really the most appropriate way to do that?
Upvotes: 2
Views: 1248
Reputation: 217810
Prefer const variable over MACRO
constexpr auto a1 = 123;
constexpr auto a2 = 6543;
constexpr auto a3 = 12;
Then to iterate over them, no need of the name, just do
for (auto e : {a1, a2, a3}) {
func(e);
}
You might want to create a variable for the list to avoid repetition if you iterate at several place.
Upvotes: 1
Reputation: 1
Another approach is to generate some C++ file containing what you want. So you'll need to set up your build for that purpose. You often use some build automation tool (such as GNU make, ninja, etc...) and you can configure it to generate some C++ file when needed (e.g. by adding a few lines in your Makefile
, if you use make
). The program generating some C++ code could be some script (e.g. in shell, awk, Python, Guile, ...), some specialized metaprogram (such as moc
for Qt programs), some other preprocessor like GPP or m4, or your own other C++ program, etc... This kind of metaprogramming approach is routinely used with C++ and C since the previous century (look into Qt moc, bison, SWIG, ... for examples).
See also this answer to a related question (with C).
You would generate some header containing stuff like
#define a1 123
#define a2 6543
#define a3 12
(you don't want =
in such #define
-s)
or you might generate some enum
like
enum number_en {
a1= 123,
a2= 6543,
a3= 12,
};
Notice that generating C++ code could be a more efficient (since build-time) solution at runtime than other (e.g. std::map
based) approaches.
Upvotes: 2
Reputation: 44329
Is there a way in the code to somehow iterate over them to construct their name with strings and then get the define value of that constructed strings?
No, there is no way to do that using defines.
You'll need to put the values into some container to be able to iterate the values.
If you just want to store the values, you can use a std::vector.
If you want to have both a name and a value, you can use std::map. Something like:
#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;
}
Upvotes: 2
Reputation: 2070
Macro are parsed by the preprocessor and are unknown to the processor (you can't use them in your code).
If you want to associate a name to a value, you can use a const map and constexpr expression :
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}
}
You need C++11 (or above) in order for this to work.
Upvotes: 1
Reputation: 1431
Lines starting with #
are evaluated by the preprocessor - the compiler won't see them, only their effects. C++ code can therefore not interact with preprocessor variables, as they don't exist anymore when the code is compiled.
Constants can be defined that way, but C++ offers better approaches. For example they can be wrapped in namespaces to avoid name collisions.
//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
To get more explanations about the type defining suffixes have a look at integer literals and floating point literals. You might also want to read up on constexpr later when you are more comfortable with C++ to explore compile time constant expressions.
Upvotes: 3