How to design a file container in C++? - c++

My plan is to build a fileContainer that consists mainly of a std::map that associate specific files to an ID. Each file has for attributes a ofstream, a path (string) and a few other information.
The problem is that an ofstream cannot be copied (Why copying stringstream is not allowed?) and cannot even be moved (Why can't std::ostream be moved?). One can therefore not create file objects to then insert them into the map of the fileContainer.
What I am trying to do is something like
file f(arguments...); // create a `file`
FC.insert(f); // Note the FC is a global singleton of class `fileContainer`
...
{
file& f = FC.getFile(fileID); // find a specific file in the file container
f.open();
f.write(s1);
f.write(s2);
f.write(s3);
f.close();
}
I fail to see how such functionality could be achieved without having to copy or move a stream. Can you help me out to build this type of functionality?
Response to #πάνταῥεῖ comment
My code can produce about 20 different types of files. The types of files (which I above call ID) that are actually being produce depends upon the user input.
My goal is to have a fileContainer in which, I insert file objects. Those file objects are created while I read the input. Each file object match to a file ID. For any given file object a single file is being produced but for others, several files are being produced (information that can be gathered only during the process).
During the process, I would just look at whether a given ID is present in the fileContainer and if it is, then I write to it the associated file.
I already have a working version of the code, the issue is that it does not compile on every machine (looks like some compilers are fine with moving streams while others aren't)

If you only need std::ofstream
No problem! These are moveable.
If you need any std::ostream
Since std::ostreams cannot be copied or moved, your only option is to go back in time and store pointers instead. Use dynamic allocation to get fine control over the lifetime of your stubborn stream objects.
Abstracting away your custom container, a basic example looks like this:
std::vector<std::unique_ptr<std::ostream>> container;
container.push_back(std::make_unique<std::ostringstream>());
container.push_back(std::make_unique<std::ofstream>("/tmp/lol"));
…and so forth.
Nice, huh? #c++

Related

Is it possible to have a C++ function or macro that writes the code of another function to file as a string?

Is it possible to have a function write the contents (i.e. the actual code) of another function to a file? For instance say we have a function that adds two numbers:
int add(int a, int b){
return a + b;
}
would it be possible to have another function or macro that would write this function as a string to a file?
void functionThatWritesAddToAFile(std::string fname){
}
The reason I want this is to autogenerate my documentation examples. I want to be able to write code examples (preferably as googletests, but as simple functions is also fine) and run them, then have the code examples be saved into a file at a known location which would be read automatically by my documentation (using sphinxs .. literalinclude:: fname directive). This way, when code changes, the examples automatically get updated.
I don't have much recent experience with C++ but I think it's possible to at least read the contents of a text file and copy it over to another? Obviously you can't have the code you'd like to copy running at the same time but if you need just to copy the contents and save it to a different location that's possible. The function could maybe look like:
open file
read contents
store contents as string
create new file at location
write contents in new file
close file
...something like this?
Python uses open(),read(),write() functions/methods and I'd imagine C++ has something similar

An in code class auto generator from a string of text or some other mechanism

I would like to be able to automatically generate a class in code if possible.
I know that I can have a text or script file that can be opened and the contents of that file be loaded into either a vector of strings or a string stream, and from there write back to a file or set of files to generate a class. I'm not interested in the details of the parsing aspect and this is not what I'm actually after.
Let's say I have a text file that looks something like this: My current pseudo file above is much longer with more verbose detailed explanations; but omitted here for simplicity. If you feel that it is needed don't hesitate to ask and I will post it.
script
// The finalized scripting file & its parser will not have any comments within code sections.
// Comments can be found before & after the <begin:file> & <end:file> sections
// This is the beginning of the file and whether or not a header and or cpp file
// is generated or not. If not then the idea is to generate the class in code directly.
// <begin:file "Foo.h"> // header only otherwise
// <being:file "Foo.h", "Foo.cpp"> for both header and cpp
<begin:file>
<class:"Foo">
<private:>
<variables: int=mX,mY,mZ float=mWidth,mHeight>
<public:>
<constructor:defualt=t, init=t>
<constructor:copy=t> // automatically generates both copy() & operator=() as = default;
<constructor:copy=f> // declares both copy() & operator() as = delete;
<destructor:default=t>
<end:class>
<end:file>
In the above script where I have <begin:file> since there are no strings after it; this means I do not want to write to files to create a header and or cpp file. Since they are omitted I would like to generate this class in code.
I do not want to resort to using macros. I could use templates if possible or some other mechanism.
What I am not sure about is this: let's say I'm at the part where I read in <class:"Foo"> this will tell my parser that I want a class named Foo and this would be it's shell:
class Foo {};
As expected, however we can not write the ending }; part yet because we have not reached the <end:class> part. So at this point we need to write out class Foo { and the part or problem that I'm seeing here is I do not know how I would be able to take the text or string such as std::string name("Foo");
and appended that after the c++ key word class. Pseudo example:
{
std::string name("Foo");
class name {
public:
int x;
};
std::cout << name << std::endl; // compiles and prints to the console "Foo"
std::cout << name.y << std::end; // will not compile.
}
The problem here is that after c++'s key word class it is expecting an identifier and the compiler will not accept this. The compiler will declare a string named name that has the contents of "Foo", then below when trying to declare the class using that string, it doesn't see the string and names to the class with the identifier name. Then if you try to use the class afterwards it doesn't find the class at all but rather it finds the string called name. Is it possible to use some kind of already built in feature to append the needed text here to automatically generate a class within code without having to type it out? I am not sure of how to extract the text from a string to use that as the identifier of the class's name.
Conclusion
From reading the comments and answer provided in my related question; it then proves my initial assumptions that I didn't mention to be true. It can not be done. This does resort into having to write the class to their respective files from the parsers point of view.
Sorry, but this just isn't how C++ works. A compiler understands things like the keyword class and the names of members, and typically puts all that understanding to use to convert all that into machine code, which normally uses just lots of raw pointers and offsets, not the names of members or things like that. Only after the compiler is finished, you run your program, and a typical program does not itself contain much of any capability at all to understand things like classes, member names, or assignment operators.
So what options do you have? You could write some utilities that are capable of doing some of the things a general class would do, but you won't be able to refer to it in the same ways as a class the compiler learned about from a header file within your program. This might look something like:
{
CustomClass myclass( "Foo.cls" );
CustomObject obj = myclass.create(); // default constructor
CustomObject obj_copy = obj; // copy constructor
}
Or you might do something that compiles and loads plugins at runtime, though there are a few complications to attempting that. This still doesn't let you use the custom class like one compiled into your program, but it allows arbitrary C++ code (which is both powerful and dangerous, since someone could accidentally or maliciously break just about anything that way). This would involve converting your configuration file to an actual temporary C++ source file you write out, running the compiler with special options to create a "shared library" (Unix, including Linux) or "DLL" (Windows), then loading that library using dlopen (many Unix flavors including Linux) or LoadLibrary (Windows). And for the compile step, this means any computer where you run your program needs the compiler installed, and it should probably be a reasonably close version to the compiler version you used to compile your program. If this compiler is on a special path, how will your program be told that path?
Plus you would need to design a plugin architecture, considering things like:
How does the plugin interface with the program? Does it provide a function that just inputs and outputs vectors of strings? Does it provide a function to create a class object derived from some abstract base class?
If the plugin needs to use any base classes or specialized functions specific to your program, how will you make sure the needed header files are provided to the compiler when compiling the plugin?

writing structures using fstream in c++

Please tell me that the following line writes the address of the structure variable to the file or it writes the values of members of the structure.
file_write.write((char*)&structure_data,sizeOfStructure);
Where file_write is fstream's object and "structure_data" is a struct having 3 members of integer datatypes. Thanks.
This line:
file_write.write((char*)&structure_data,sizeOfStructure);
takes whatever structure_data is, and just copies those blob of bytes that makes up structure_data to a file.
It doesn't figure out what the members are. Also, this is the cause for thousands of SO questions that erroneously do coding like this, where structure_data cannot be written to a file this way and have the file contents make sense. It is quickly discovered that the contents of the file are useless when an attempt to read back the data into a program
is unsuccessful.
Most of the time in those scenarios structure_data would contain pointers, or members that are not C-layout compatible, i.e. non-POD types such as std::string or std::vector, that basically renders this technique of writing to a file like this totally useless (and invalid).
Look up object serialization such as this link on the topic

Accessing files made with mktemp for Linux through C++

I am trying to create a temporary file on a Linux system, but interfacing through C++ (so that the Linux commands are run through the C++ program).
To do so, I am using mktemp, which produces a temporary file.
I would need to later refer back to this file.
However, the filename is randomly generated and I am wondering if there is an easy way to access the filename.
The big honking comment in mktemp(3)'s manual page explicitly tells you to use mkstemp(3) instead of mktemp(3), and explains the good reason why it is so.
If you actually read the manual page for mkstemp(3) it clearly explains that the library function modifies the character buffer that's passed to it as a parameter to reflect the actual name of the created temporary file.
So to determine the name of the temporary file, simply refer to the character buffer you passed to this library function.

Is it possible to create a struct type based on file contents?

Is it possible in C++ to create a struct type based on file contents?
STRUCT_NAME
int var1;
int var2;
string v3;
STRUCT NAME *pointer;
The first line would be the name of the struct, the other lines would be the variables
Do you mean on the fly, when your application is running? No, you can't do that, all types must be known at compile time. Of course, you can always create some kind of container object that could be configured dynamically during run-time, but that is a much more advanced system.
On the other hand, if you mean to do this once when you build you application, you could write a simple tool that eats your text file and emits a C++ header file, that you later could use when compiling.
If you are reading from a file and trying to create this struct,
--> if in same program, i.e. runtime then NO; because you can not compile the source code which is presently executing
--> for some different source code which is yet to be compiled and you are manipulating using file operations then YES
No. The closest you can come is an std::map<std::string, boost::any> (or boost::variant if you can limit the set of types).
Whatever #lindydancer #iammilind #james are saying is correct.. You cannot do it in single go. You may get work around (Though thats not professinal way of doing) like this :
1. First read the file in which your structure is define and create new file(Cpp and h files).
2. Now compile new file and provide new exe file to your user, you can do this process in background so that for user its all dynamic.. (But atlease someone has to do this work...)