How to get the size of data stored in "any" in c++17?
Asked Answered
I

1

0

suppose i have a function like this

int writetofile(wstring name, any sdata){
  ...
   return error;
}

This function have no idea about what data would be stored but would need to know the size of the data stored in sdata. Although it is easy to determine the type of data stored in the sdata but i don't think there is some easy way to know about the size of data in sdata.


i have a data structure which has members of type wstring. Now We cant write that data structure directly to the file as it contains that wstring. As far as i have researched on internet, the best way to write wstring or string, is to write size first of the string and then the string. Then when i would read the string first reading the size then after this read that much of size.

for this i have made a function.

int filemanager::write(any data, fileid uid, DWORD *byteswritten) const
{
    // files is a map<fileid, fileinfo> where fileinfo is a struct which has 
    // members including file's name and handle 
    // fileid is a typedef of int
    if (!files.count(uid)) return -1;
    if (!data.has_value()) return -2;
    if (data.type() == typeid(wstring)) {
        DWORD sz1, sz2;
        wstring str = any_cast<wstring>(data);
        size_t sz3 = str.length()*sizeof(wchar_t);
        if (sz3 == 0) return -2;
        if (FALSE == WriteFile(files[uid].handle, &sz3, sizeof(size_t), &sz1, NULL)){
            return GetLastError();
        }
        if (FALSE == WriteFile(files[uid].handle, str.c_str(), sz3, &sz2, NULL) && sz2 != sz3) {
            return GetLastError();
        }
        if (byteswritten != nullptr) *byteswritten = sz1 + sz2;
    }
    else {
        // now if the type is not a wstring then just write it to a file
        // here i would need the size of the data stored in the data
    }
    return 0;
}
Intertidal answered 16/8, 2018 at 16:58 Comment(8)
Can you count the bytes in sdata?Besprent
Possible duplicate of Retrieving size of datatype from std::type_infoDemicanton
How would you use this information?Drosophila
@n.m. i want to write it a fileIntertidal
How do you do that? Please show some code.Drosophila
Judging by the name writetofile, your plan is to write the contents of the type contained in the any object to a file. This will fail horribly for types that are not trivially copyable. Take std::vector for instance; if you copy its contents to a file, you'll likely copy 3 pointers. You need to copy the data the vector is holding in dynamically allocated memory instead. Please use a proper serialization library. Anyway, I don't see how you're going to make serialization without knowing the type workNealon
then just write it to a file HOW?!?! Suppose you know the size of the data. For the sake of the argument let's assume it's 42. What do you do next?Drosophila
Proceed with caution. All of the crazy rigamarole, or some variant of it, you do for wstring you would have to do for any other complex type you may be passing in any. With any that is an insane number of different possibilities. You could restrict the possibilities with std::variant, but I think you are better off heading down a different path.Sequoia
W
11

std::any is not the correct tool for what you're trying to do. It is a tool primarily intended for communicating between points A and B, where both points know what the type is, but the communication needs to happen through some intermediate code C that doesn't need to know the type.

If B needs to try a bunch of different casts to see which value was provided, any is not the right tool for that job. The cast is there for type safety reasons: to have a well-defined failure path in the event that the wrong any was provided. That is, to make sure that A and B are communicating correctly. It's not there so that you can try a bunch of different things.

You can't ask any what the size of the stored object is because you should already know the answer. And even if you didn't know the answer, you could never validly use that answer.

Take your use case, for example. any is not TriviallyCopyable, so it is not legal C++ to copy its bytes directly to a file and then copy them back. And even if it were conceptually OK to do so, any may only be storing a pointer to the object it contains. So you'd just be writing a pointer to the file.

Serialization in C++ is not going to be as simple as you're trying to make it.

Whiffler answered 16/8, 2018 at 17:32 Comment(1)
Took the words out of my mouth. boost::variant is probably the correct tool here.Collier

© 2022 - 2024 — McMap. All rights reserved.