C++: Is it posible to set the type of a void-pointer, variant-object or any-object in execution time?

孤者浪人 提交于 2021-01-28 23:22:14

问题


Void-pointer, variant-objects and any-objects are amazing because they can store many different types in the same variable. But I have a problem with them, I need to specify their type (creating and/or de-referencing them) in the execution time, is it possible?

To be more clear, for example, as far I know, to create and de-reference them I have to do this:

void* ptr = new int(8);
variant<int, float> var = 8;
any a = 8;
...
cout << *(int*)ptr;
cout << get<int>(var);
cout << any_cast<int>(a);

As you can see, in all cases the type must be "written in the code" (programming-time?). It would be excellent if that type could be determinate in the execution time. Let me dream... if, for example, we could "store a type" as an object, we could do this:

TYPE mi_tipo;
...
mi_tipo = int;   // or float, or char or any other...
...
void* ptr = new mi_tipo();
cout << *(mi_tipo*)ptr;

Something like this is possible? If not, how would you do this? I'm trying to do simulate a compiler perform, so I need an structure which can store any type of variables, and so I need an efficient way of de-reference them in execution time.


回答1:


C++ is a statically typed language. The type of any expression must be known at compile-time. While compile-time code can do limited forms of type computation, and even type generation to a degree, all of that exists only at compile-time.

Once you reach the runtime, everything has to be known. Dynamic polymorphism through base classes and virtual functions exist, but at the point the actual object is created, you have to know what type it is. There are techniques which can allow dynamically determining which polymorphic derived class to instantiate, but they all ultimately boil down to a bunch of conditional statements and a hard-coded (even if generated through templates) set of types.




回答2:


Something like this is possible?

Except for using mi_tipo = int;, no, c++ is a statically typed language.

if no, how would you do this?

Decide on an interface for your types, and enumerate all possible type and write interfaces for them to hide implementation.

#include <map>
#include <stdexcept>
#include <iostream>
#include <memory>
#include <sstream>

struct AtypeInterface {
    AtypeInterface() {}
    virtual ~AtypeInterface() {}
    virtual std::string format() { throw std::runtime_error("invalid"); return ""; }
};

template<typename T>
struct Atype : AtypeInterface {
    T val;
    Atype(T val) : val(val) {}
    ~Atype() {}
    std::string format() override { 
       return std::to_string(val);
    }
};
struct AtypeVoidPointer : AtypeInterface {
    void *p;
    AtypeVoidPointer(void *p) : p(p) {}
    ~AtypeVoidPointer() {}
    std::string format() override {
        // custom behavior if needed
        if (p == NULL) {
             return "och no! the pointer is null!\n";
         } else {
             std::stringstream s;
             s << p;
             return s.str();
         }
    }
};

int main() {
   std::unique_ptr<AtypeInterface> mi_typo;
   mi_typo = std::make_unique<Atype<int>>(5);
   std::cout << mi_typo->format() << '\n';
}

Such design looks "good enough".




回答3:


Something like this is possible?

Yes, but you need to store the type information yourself somehow. There is no reflection in C++ so far, static or otherwise.

There are also tricks around RTTI (Run-Time Type Information), but I wouldn't recommend those.

how would you do this?

Use a tag to carry which type is inside, for instance, an enum class.

Otherwise, use standard or third-party solutions that do this for you, like std::variant.



来源:https://stackoverflow.com/questions/63221276/c-is-it-posible-to-set-the-type-of-a-void-pointer-variant-object-or-any-obje

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!