How to Initialize a vector<typeinfo>?

Viewed 381

I am able to do this:

std::vector<int> vec = { 1, 2, 3, 4, 5 };

But I am not able to do this:

std::vector<const type_info&> ClassBlackList = { typeid(Class1), typeid(Class2) };

compiler says pointer to reference is illegal or

std::vector<const type_info> ClassBlackList = { typeid(Class1), typeid(Class2) };

compiler says Error C2338 The C++ Standard forbids containers of const elements because allocator is ill-formed.

or

std::vector<type_info> ClassBlackList = { typeid(Class1), typeid(Class2) };

Compiler says: Error C2280 'type_info::type_info(const type_info &)': attempting to reference a deleted function

I am able not able to do push_back either. What is the solution to have a vector or list of type_info?

3 Answers

You can use pointers

std::vector<const std::type_info*> v = { &typeid(Class1), &typeid(Class2) };

This is valid because typeid returns a reference to an object with static storage duration.

You cannot have a vector of references, for several fundamental reasons. C++ simply does not work this way. You can, however, employ std::reference_wrapper to get pretty much the same result:

#include <functional>
#include <vector>
#include <typeinfo>

class A {
};

int main()
{
    std::vector<std::reference_wrapper<const std::type_info>> avec;

    auto &t=typeid(A);

    avec.push_back(t);

    const std::type_info &i=avec[0];

    return 0;
}

You can't have arrays of references so you could wrap them in std::reference_wrappers:

#include <functional>
#include <typeinfo>
#include <vector>

std::vector<std::reference_wrapper<const std::type_info>> ClassBlackList = {
    typeid(Class1), 
    typeid(Class2) 
};

The name ClassBlackList implies that you will search it a lot and also that the elements in the list are to be unique. In that case, you may want to use a std::set instead.

Example:

#include <functional>
#include <iostream>
#include <typeinfo>
#include <set>

struct Class1 {};
struct Class2 {};
struct Class3 {};

struct comp { // a functor to compare reference wrapped type_info's
    std::size_t operator()(const std::reference_wrapper<const std::type_info>& lhs,
                       const std::reference_wrapper<const std::type_info>& rhs) const
    {
        return std::less<const std::type_info*>{}(&lhs.get(), &rhs.get());
    }
};

int main() {   
    std::set<std::reference_wrapper<const std::type_info>, comp> ClassBlackList = {
        typeid(Class1), 
        typeid(Class2) 
    };

    // try to insert typeid(Class3) twice, it only succeeds the first time

    auto[it1, inserted1] = ClassBlackList.insert(typeid(Class3));
    std::cout << "inserted: " << inserted1 << '\n';

    auto[it2, inserted2] = ClassBlackList.insert(typeid(Class3));
    std::cout << "inserted: " << inserted2 << '\n';
}

Output:

inserted: 1
inserted: 0
Related