Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving size of datatype from std::type_info

Tags:

c++

std

c++03

In C++03, when you use the operator typeid, a type_info object is returned.

Is it possible to retrieve the size of the given type based only on this result, such as returned by the sizeof operator?

For example:

std::type_info info = typeid(int);
int intSize = sizeof(int);
int intSize2 = info.getSize(); // doesn't exist!

The issue is that we use a third-party multi array class that gives back a type_info, but not the size of the type.

like image 514
Schiavini Avatar asked Dec 17 '14 10:12

Schiavini


People also ask

What is std :: type_info?

std::type_info The class type_info holds implementation-specific information about a type, including the name of the type and means to compare two types for equality or collating order.

What does Typeid return C++?

The typeid operator returns an lvalue of type const std::type_info that represents the type of expression expr. You must include the standard template library header <typeinfo> to use the typeid operator.

What is the use of Typeid () function?

The typeid operator allows the type of an object to be determined at run time. The result of typeid is a const type_info& . The value is a reference to a type_info object that represents either the type-id or the type of the expression, depending on which form of typeid is used.

What is std :: Type_index?

std::type_index The type_index class is a wrapper class around a std::type_info object, that can be used as index in associative and unordered associative containers. The relationship with type_info object is maintained through a pointer, therefore type_index is CopyConstructible and CopyAssignable.


Video Answer


1 Answers

The best way I can see (I would like to be proven wrong) is to register the types beforehand, like this:

#include <typeinfo>
#include <iostream>
#include <stdexcept>
#include <map>
#include <vector>

typedef std::map<const std::type_info*, std::size_t> sizes_container; // we cannot use std::type_index, but that's ok - typeid returns const std::type_info&, which refers to an object which lives during the entire lifetime of the program

sizes_container& sizes() // wrapped in a function to avoid static initialization order fiasco
{
    static sizes_container s;
    return s;
}

template<typename T>
void register_size() // Register the type. Can be called multiple times for the same type.
{
    sizes().insert(sizes_container::value_type(&typeid(T), sizeof(T)));
}

class no_such_type : public std::domain_error
{
public:
    no_such_type(const std::string& str) :
        std::domain_error(str)
    {

    }
};

std::size_t get_size(const std::type_info& typeinfo)
{
    sizes_container::iterator it = sizes().find(&typeinfo);
    if(it != sizes().end())
    {
        return it->second;
    }
    else
    {
        throw no_such_type(std::string("No type ") + typeinfo.name() + " registered");
    }
}

int main()
{
    register_size<int>();
    register_size<std::vector<int> >();

    std::cout << get_size(typeid(int)) << "\n" // get the size from std::type_info, possibly at runtime
              << get_size(typeid(std::vector<int>)) << "\n" << std::flush;
    std::cout << get_size(typeid(long)); // if the type isn't registered, the exception no_such_type is thrown
}

Possible output:

4
24

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
terminate called after throwing an instance of 'no_such_type'
  what():  No type l registered

If you can control how you create the arrays (for example, with a factory method) you can directly register the type here.

like image 177
milleniumbug Avatar answered Sep 19 '22 03:09

milleniumbug