Initialize vector of strings from text files at compile time - c++

I'm working on a project that has a directory of files: myFiles.
I need something like:
const vector<string> configs = { contents_of_file0, contents_of_file1, ... };
It is desired that the contents of these files be part of the binary, as opposed to being read at runtime.
Is there a clean way to do this?
Today, there is a massive hack, the contents of all the files are concatenated into a single #define, by a build script.
#define contents "a supper massive string that is too large for some compilers to ingest"
This #define is later parsed at runtime.
I'm looking for a cleaner way...

Is there a clean way to do this?
There is proposed feature for this purpose that may end up in a future standard.
Until then, you can use meta programming: Generate source code from the input file. The generated source should contain the initialiser based on the file. An open source program exists that can do this: xxd
concatenated into a single #define
I don't see an advantage to this. If you want separate strings, then generate separate initialisers. I also don't see a need for a macro.
I also recommend carefully re-considering whether it even makes sense to want this. Loading a massive executable isn't any faster than reading large files, and reading files is more flexible.

This #define is later parsed at runtime. This is the wrong statement, define is a preprocessor, which is done in the very early stage of compiling. And for static strings, it can be parsed in build time since c++17, this is also a consideration solution to generate constepr vector when combined with constexpr vector from c++2a.
May consider using the include hack for simplicity, if you use it please don't forget to set up the dependency for tbl file in makefile:
For the source file:
int main(int argc, char* argv[]) {
std::vector<std::string> vec = {
#include "1.tbl"
#include "2.tbl"
};
for (auto& v : vec) {
std::cout << v << std::endl;
}
return 0;
}
For the table file 1.tbl:
"1","2","3",
For the table file 2.tbl:
"a", "b","c",
We get the output:
1
2
3
a
b
c

Related

How to remember or store functions (and all the other stuff) in C++ or code in general?

I am new to coding and C++ and I am asking myself how to store or structure all these little (sub)functions and code in a proper way?
For example a function to sum up all values of an array or the Fibonacci numbers or all the other little functions and programs which are basic stuff esp. pointers etc.!?
My idea is to create an ordinary .txt sheet and to copy and paste them all there in just one .txt
For me it´s important to have them all at one place. How do you pros handle this or do you guys really have most of this stuff in your local memory (brain). For me it seems impossible to remember all the functions and algorithms or even the syntax (when the code starts to get nasty).
If I understood your question correctly then you are asking where/how we store reusable snippets of code in an easy to access way. There are number of methods to accomplish this, one which you have mentioned is to simply use a text file and copy paste as needed, but in my opinion this is a bit archaic.
I have two main methods I like to use, first if it's code I want to access online or is rather large functions I plan to reuse, I simply make a gist of it and leave it there, ready to be accessed as needed. Usually I name it something descriptive so when I look through all my gists, I can find the ones I need quickly.
The second method, and the stuff I do for code that mainly gets reused is to make snippets using my IDE's configuration files. Such snippets usually are written in JSON format and include a trigger word, for example: for and then when you hit a special key, typically tab, it will expand the snippet to something like:
for(int i = 0; i < n; i++) {
// Code goes here...
}
And we can simply just hit tab to edit the starting condition, the ending condition, the increment and the variable names. Snippets are very versatile and you can write as many as you want. If you use Visual Studio Code you can take a look at the C++ tools extension which has some default snippets.
Lastly I keep a handy bookmark to a C++ reference site and look up stuff in the STL as needed so I'm not reinventing the wheel or making extra work for myself.
Welcome to StackOverflow!!!
In C++ you generally put all your functions in a header and cpp file to store all the functions. You then go to the main and pick up a reference to the header file.
// A2DD.h
#ifndef A2DD_H
#define A2DD_H
namespace A2DD{
int GetSum(int x, int y);
}
#endif
and the implementation goes in the CPP file:
// A2DD.cpp
#include "A2DD.h"
int A2DD::GetSum(int x, int y){
return x + y;
}
Then go the main.cpp
#include "A2DD.h"
int main(){
std::cout << GetSum(2, 2) << std::endl;
}
As far as remembering the functions, you can simply take a quick look at the header file which declares the functions (no implementation)

C++ __TIME__ is different when called from different files

I encountered this strange thing while playing around with predefined macros.
So basically, when calling __TIME__ from different files, this happens:
Is there anyway I can fix this? Or why does this happen?
All I am doing is printf("%s\n", __Time__); from different functions in different sources.
Or why does this happen?
From the docs:
This macro expands to a string constant that describes the time at which the preprocessor is being run.
If source files are compiled at different times, then the time will be different.
Is there anyway I can fix this?
You could use a command line tool to generate the time string, and pass the string as a macro definition to the compiler. That way the time will be the same for all files compiled by that command.
To answer your original question: __TIME__ is going to be different for different files because it specifies the time when that specific file was compiled.
However, you're asking X-Y problem. To address what you're actually trying to do:
If you need a compilation-time value, you're better off letting your build system specify it. That is, with make or whatever you're using, generate a random seed somehow, then pass that to the compiler as a command-line option to define your own preprocessor macro (e.g. gcc -DMY_SEED=$(random_value) ...). Then you could apply that to all C files that you compile and have each of them use MY_SEED however you want.
Well, I think your use case is kind of weird, but a simple way to get the same time in all files is to use __TIME__ in exactly one source file, and use it to initialize a global variable:
compilation_time.h:
const char *compilation_time;
compilation_time.c:
#include "compilation_time.h"
const char *compilation_time = __TIME__;
more_code.c:
#include "compilation_time.h"
...
printf("%s\n", compilation_time);
If you really want to construct an integer as in your comment (which may be non-portable as it assumes ASCII), you could do
seed.h:
const int seed;
seed.c:
#include "seed.h"
const int seed = (__TIME__[0] - '0') + ...;
more_code.c:
#include "compilation_time.h"
...
srand(seed);

Function to call #include macro from a string variable argument?

Is it possible to have a function like this:
const char* load(const char* filename_){
return
#include filename_
;
};
so you wouldn't have to hardcode the #include file?
Maybe with a some macro?
I'm drawing a blank, guys. I can't tell if it's flat out not possible or if it just has a weird solution.
EDIT:
Also, the ideal is to have this as a compile time operation, otherwise I know there's more standard ways to read a file. Hence thinking about #include in the first place.
This is absolutely impossible.
The reason is - as Justin already said in a comment - that #include is evaluated at compile time.
To include files during run time would require a complete compiler "on board" of the program. A lot of script languages support things like that, but C++ is a compiled language and works different: Compile and run time are strictly separated.
You cannot use #include to do what you want to do.
The C++ way of implementing such a function is:
Find out the size of the file.
Allocate memory for the contents of the file.
Read the contents of the file into the allocated memory.
Return the contents of the file to the calling function.
It will better to change the return type to std::string to ease the burden of dealing with dynamically allocated memory.
std::string load(const char* filename)
{
std::string contents;
// Open the file
std::ifstream in(filename);
// If there is a problem in opening the file, deal with it.
if ( !in )
{
// Problem. Figure out what to do with it.
}
// Move to the end of the file.
in.seekg(0, std::ifstream::end);
auto size = in.tellg();
// Allocate memory for the contents.
// Add an additional character for the terminating null character.
contents.resize(size+1);
// Rewind the file.
in.seekg(0);
// Read the contents
auto n = in.read(contents.data(), size);
if ( n != size )
{
// Problem. Figure out what to do with it.
}
contents[size] = '\0';
return contents;
};
PS
Using a terminating null character in the returned object is necessary only if you need to treat the contents of the returned object as a null terminated string for some reason. Otherwise, it maybe omitted.
I can't tell if it's flat out not possible
I can. It's flat out not possible.
Contents of the filename_ string are not determined until runtime - the content is unknown when the pre processor is run. Pre-processor macros are processed before compilation (or as first step of compilation depending on your perspective).
When the choice of the filename is determined at runtime, the file must also be read at runtime (for example using a fstream).
Also, the ideal is to have this as a compile time operation
The latest time you can affect the choice of included file is when the preprocessor runs. What you can use to affect the file is a pre-processor macro:
#define filename_ "path/to/file"
// ...
return
#include filename_
;
it is theoretically possible.
In practice, you're asking to write a PHP construct using C++. It can be done, as too many things can, but you need some awkward prerequisites.
a compiler has to be linked into your executable. Because the operation you call "hardcoding" is essential for the code to be executed.
a (probably very fussy) linker again into your executable, to merge the new code and resolve any function calls etc. in both directions.
Also, the newly imported code would not be reachable by the rest of the program which was not written (and certainly not compiled!) with that information in mind. So you would need an entry point and a means of exchanging information. Then in this block of information you could even put pointers to code to be called.
Not all architectures and OSes will support this, because "data" and "code" are two concerns best left separate. Code is potentially harmful; think of it as nitric acid. External data is fluid and slippery, like glycerine. And handling nitroglycerine is, as I said, possible. Practical and safe are something completely different.
Once the prerequisites were met, you would have two or three nice extra functions and could write:
void *load(const char* filename, void *data) {
// some "don't load twice" functionality is probably needed
void *code = compile_source(filename);
if (NULL == code) {
// a get_last_compiler_error() would be useful
return NULL;
}
if (EXIT_SUCCESS != invoke_code(code, data)) {
// a get_last_runtime_error() would also be useful
release_code(code);
return NULL;
}
// it is now the caller's responsibility to release the code.
return code;
}
And of course it would be a security nightmare, with source code left lying around and being imported into a running application.
Maintaining the code would be a different, but equally scary nightmare, because you'd be needing two toolchains - one to build the executable, one embedded inside said executable - and they wouldn't necessarily be automatically compatible. You'd be crying loud for all the bugs of the realm to come and rejoice.
What problem would be solved?
Implementing require_once in C++ might be fun, but you thought it could answer a problem you have. Which is it exactly? Maybe it can be solved in a more C++ish way.
A better alternative, considering also performances etc., to compile a loadable module beforehand, and load it at runtime.
If you need to perform small tunings to the executable, place parameters into an external configuration file and provide a mechanism to reload it. Once the modules conform to a fixed specification, you can even provide "plugins" that weren't available when the executable was first developed.

Initialize vector of hardcoded int for different platforms

I have a problem with an initialization of a vector of integers named id_vectorthat don't need to change.
the initializer is done like this:
static int id[4]{200,300,400,500};
id_vector = std::vector<int> (id,id + (sizeof(id)/sizeof(int)));
So far so good. but now we need to have different versions of this software, and I would like to choose a different id array depending on the version. The only way I can think of is to do it inside a #ifdefor some sort of macro, but I was wondering if someone knows a better way to do it.
I was thinking something like a namespace but I don't know if this is a good use for it.
UPDATE
Had a typo in the code, sorry about that. Sorry if I didn't make myself clear but basically this is a list of valid ids and there are two versions that need different valid ids. Don't think is necessary to add more code.
If you need to put different values for different platforms, and you need the change to happen in code (as opposed to, say, a configuration file) you will end up with an #ifdef in your code. Here is one example of how you can do it:
static int id[4]{
#ifdef PLEFTORM_1
200,300,400,500
#endif
#ifdef PLEFTORM_2
100,200,410,522
#endif
};
id_vector = std::vector<int> (id,id + (sizeof(id)/sizeof(*id)));
Another solution may be to put all platform-dependent stuff in separate files, and conditionally include that file. This may reduce the number of #ifdefs to 1, but the overall code may end up being harder to read.
Of course you can change your strategy, and place platform-specific IDs in a configuration file. This would help you avoid conditional compilation, at the expense of introducing a run-time dependency on the configuration file.
Namespaces ?
namespace PLATFORM_A
{
static int id[4]{200,300,400,500};
}
namespace PLATFORM_B
{
static int id[4]{500,400,300,200};
}
using namespace USE_PLATFORM;
...
id_vector = std::vector<int> (id,id + (sizeof(id)/sizeof(int)));
With g++ -DUSE_PLATFORM=PLATFORM_A ... or g++ -DUSE_PLATFORM=PLATFORM_B ... or however you setup USE_PLATFORM....
std::vector<int> id_vector (id,id + (sizeof(id)/sizeof(int)));
id_vector = std::vector<int> (id, id + (sizeof(id)/sizeof(*id)));

get the value of a c constant

I have a .h file in which hundreds of constants are defined as macros:
#define C_CONST_NAME Value
What I need is a function that can dynamically get the value of one of these constants.
needed function header :
int getConstValue(char * constName);
Is that even possible in the C langage?
---- EDIT
Thanks for the help, That was quick :)
as i was thinking there is no miracle solution for my needs.
In fact the header file i use is generated by "SCADE : http://www.esterel-technologies.com/products/scade-suite/"
On of the solution i got from #Chris is to use some python to generate c code that does the work.
Now its to me to make some optimizations in order to find the constant name. I have more than 5000 constants O(500^2)
i'm also looking at the "X-Macros" The first time i hear of that, home it works in C because i'm not allowed to use c++.
Thanks
C can't do this for you. You will need to store them in a different structure, or use a preprocessor to build the hundreds of if statements you would need. Something like Cogflect could help.
Here you go. You will need to add a line for each new constant, but it should give you an idea about how macros work:
#include <stdio.h>
#define C_TEN 10
#define C_TWENTY 20
#define C_THIRTY 30
#define IFCONST(charstar, define) if(strcmp((charstar), #define) == 0) { \
return (define); \
}
int getConstValue(const char* constName)
{
IFCONST(constName, C_TEN);
IFCONST(constName, C_TWENTY);
IFCONST(constName, C_THIRTY);
// No match
return -1;
}
int main(int argc, char **argv)
{
printf("C_TEN is %d\n", getConstValue("C_TEN"));
return 0;
}
I suggest you run gcc -E filename.c to see what gcc does with this code.
A C preprocessor macro (that is, something named by a #define statement) ceases to exist after preprocessing completes. A program has no knowledge of the names of those macros, nor any way to refer back to them.
If you tell us what task you're trying to perform, we may be able to suggest an alternate approach.
This is what X-Macros are used for:
https://secure.wikimedia.org/wikipedia/en/wiki/C_preprocessor#X-Macros
But if you need to map a string to a constant, you will have to search for the string in the array of string representations, which is O(n^2).
You can probably do this with gperf, which generates a lookup function that uses a perfect hash function.
Create a file similar to the following and run gperf with the -t option:
struct constant { char *name; int value; };
%%
C_CONST_NAME1, 1
C_CONST_NAME2, 2
gperf will output C (or C++) code that does the lookup in constant time, returning a pointer to the key/value pair, or NULL.
If you find that your keyword set is too large for gperf, consider using cmph instead.
There's no such capability built into C. However, you can use a tool such as doxygen to extract all #defines from your source code into a data structure that can be read at runtime (doxygen can store all macro definitions to XML).