问题
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