km9c3uwc
km9c3uwc

Reputation: 61

How to check a runtime type under void* pointer (simple types allowed, no base class)?

How to check what is a runtime type under a void* pointer. For example, how to write such a function:

void f(void *p) {
  // check if *p is an int or a vector
}

Modern C++ versions (14, 17) are welcome. Future versions are also interesting as an information for the future.

There is no base class nor common virtual methods and simple types are allowed, so How to determine actual object type at runtime in C++; is not exactly relevant.

EDIT:

OK, in certain cases, if the caller knows the real type of the pointer, overloads could be a solution for the simplified example above. But what about something slightly more complex:

using ::std::vector;

void f(vector<void*> v) {
  // check if particular *v[i]'s are ints or vectors
}

Also void* in a function declaration was not my idea.

Upvotes: 1

Views: 311

Answers (3)

Red.Wave
Red.Wave

Reputation: 4201

Forget about void*. It is a one way ticket; once you step in, there is no way back and all static type info is gone for good. If the set of used types is unbound, go for std::any(c++17 or boost). It may trigger dynamic allocation, but also has small value optimization: http://en.cppreference.com/w/cpp/utility/any But if the set of used types is countable and bound, consider std::variant(c++14 or boost). You may investigate static visitor pattern: http://en.cppreference.com/w/cpp/utility/variant

Upvotes: 0

Vittorio Romeo
Vittorio Romeo

Reputation: 93264

This is not possible for primitive types, and honestly it is a terrible idea. void* is just an address to anything - there's no information here that can be used to deduce what the actual type of the pointee is.

In practice, one of the reasons why this can be done for polymorphic types is because run-time type information can be stored in the vtable. (Note that the Standard doesn't require the use of a vtable, but it's the most common implementation.)

Upvotes: 0

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122228

It is not really clear, why you have a void* in the first place. Once you have a void* any information on the actual type is lost and the function you'd like to write is not possible in C++. If you want to call the same method with either a pointer to int or pointer to std::vector you would rather use overloads:

void f(int* p) {
     std::cout << "f called with pointer to int";
}

template <typename T>
void f(std::vector<T>* p) {
     std::cout << "f called with pointer to vector";
}

Upvotes: 3

Related Questions