简体   繁体   中英

std::type_info for array of runtime defined length

When using typeid(char[10]) one gets the std::type_info for char[10] .

Now I have the problem that I need to get typeid(char[n]) where n isn't constexpr .

Is there a way to do that?

My current implementation just uses templates in a recursive way to generate calls from typeid(char[1]) to typeid(char[100]) and then choose the right call with a recursive function that stops at the right number.

While this works it only works for up to 100 and if I increase it much higher it will generate a lot of code or stop compiling because of too deep recursion

Are there other possibilities?

Naive implementation that would do what I want:

const std::type_info& getTypeInfoForCharArray(size_t len) 
{
  switch(len) 
  { 
    case 1: return typeid(char[1]);
    case 2: return typeid(char[2])
    case 3: return typeid(char[3])
    case 4: return typeid(char[4])
   ... 
  } 
} 

Background

Now one might ask why I need such a function. To put it shortly, I have to integrate the definition of multiple structs from multiple DLLs where the lengths members can change and shouldn't require a recompilation of the code I work on. I need this to properly allocate and access the memory for those structs so I can call functions in those DLL.

Part of the implementation is a runtime type check for field access to avoid access violations because the C++ compiler can't check for those without knowing the struct at compile time. All this works well except for arrays.

If the answer to my question is "no, it can't be done" then I'll just have to treat arrays differently than other types.

You can use std::integer_sequence :

template <typename T>
struct Helper;

template <std::size_t ...L>
struct Helper<std::integer_sequence<std::size_t, L...>> {
    static const std::type_info &get(std::size_t len) {
        static const std::type_info *a[sizeof...(L)] = {&typeid(char[L])...};
        return *a[len];
    }
};

const std::type_info &getTypeInfoForCharArray(std::size_t len) {
    const std::size_t max = 10000;
    assert(len<=max);
    return Helper<std::make_integer_sequence<std::size_t, max+1>>::get(len);
}

int main() {
    auto &t = getTypeInfoForCharArray(10000);
    std::cout << t.name() << "\n";
}

This compiles in ~1 second with clang (with max size of 10,000).

Note, that this solution will generate all the type_info objects from 0 to max , which may need a significant amount of data (for this example, the resulting binary is ~1 MB), as the compiler needs to generate all type_info objects into the binary.

I think if you don't have the list of possible sizes beforehand, this is the best you can do (or maybe you can consider some compiler dependent solution. Like exploiting the fact the we know of the format of type_info::name() , but this is a hacky solution. But maybe this is fine, if you use this feature for debugging only).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM