c++templatestypesunionstypeinfo

C++ typeid template value into union no acceptable conversion


Im trying to build a dictionary of properties that are read in from an XML blender scene and am running into an issue with templates and getting their type_info. The containing map is setup as the name of the property and its value which is stored into a struct of typeinfo and union. Is it possible to do it this way or does it have to recognize it on the specific type? I have made attempts to initialize the struct before passing it to the map, and even to copy the binary data to the union, but it errors everytime on getting typeid(T). And I have also attempted using tuples in the map instead of the struct. here's the line causing the error

line 80 = mProperties[name] = std::make_tuple(typeid(T), d);

The error

Severity    Code    Description Project File    Line    Suppression State
Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'std::tuple<type_info,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>' (or there is no acceptable conversion)   OgreEngine  D:\SchoolAndProjects\Programs\ETGG 3802_01 Realtime Interactive Prog 2\Lab 1\OgreEngine\OgreEngine\include\component.h  80  
Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'std::tuple<type_info,int>' (or there is no acceptable conversion)   OgreEngine  D:\SchoolAndProjects\Programs\ETGG 3802_01 Realtime Interactive Prog 2\Lab 1\OgreEngine\OgreEngine\include\component.h  80  
Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'std::tuple<type_info,float>' (or there is no acceptable conversion) OgreEngine  D:\SchoolAndProjects\Programs\ETGG 3802_01 Realtime Interactive Prog 2\Lab 1\OgreEngine\OgreEngine\include\component.h  80  
Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'std::tuple<type_info,double>' (or there is no acceptable conversion)    OgreEngine  D:\SchoolAndProjects\Programs\ETGG 3802_01 Realtime Interactive Prog 2\Lab 1\OgreEngine\OgreEngine\include\component.h  80  
Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'std::tuple<type_info,bool>' (or there is no acceptable conversion)  OgreEngine  D:\SchoolAndProjects\Programs\ETGG 3802_01 Realtime Interactive Prog 2\Lab 1\OgreEngine\OgreEngine\include\component.h  80  
Error   C2280   'void *std::pair<const std::string,std::tuple<type_info,OgreEngine::Component::data>>::__delDtor(unsigned int)': attempting to reference a deleted function OgreEngine  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\xmemory 676 
Error   C2280   'void *std::pair<const std::string,std::tuple<type_info,OgreEngine::Component::data>>::__delDtor(unsigned int)': attempting to reference a deleted function OgreEngine  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\xmemory 676 
Error   C2280   'void *std::pair<const std::string,std::tuple<type_info,OgreEngine::Component::data>>::__delDtor(unsigned int)': attempting to reference a deleted function OgreEngine  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\xmemory 676 
Error   C2280   'void *std::pair<const std::string,std::tuple<type_info,OgreEngine::Component::data>>::__delDtor(unsigned int)': attempting to reference a deleted function OgreEngine  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\xmemory 676 
Error   C2280   'void *std::pair<const std::string,std::tuple<type_info,OgreEngine::Component::data>>::__delDtor(unsigned int)': attempting to reference a deleted function OgreEngine  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\include\xmemory 676 

Code:

private:
    union data
    {
        std::string sVal;
        bool bVal;
        int iVal;
        float fVal;
        double dVal;
    };
    struct propertyData {
        type_info dataType;
        data val;
    };

protected:
    GameObject* Parent;
    std::map<std::string, std::tuple<type_info, data>> mProperties;

public:
    /// Append the property of type T to the property map container
    template<typename T>
    void add_xml_property(std::string name, T d)
    {
        if (mProperties.find(name) == mProperties.end())
        {

            //struct propertyData pData = {typeid(T), d};
            //memcpy_s((void*)&pData.val, sizeof(d), (void*)&d, sizeof(d));
            mProperties[name] = std::make_tuple(typeid(T), d);
        }
    };

Solution

  • The copy constructor of std::type_info is deleted so you can't copy those objects into your map. However, typeid() ...

    ... refers to an object with static storage duration, of the polymorphic type const std::type_info or of some type derived from it.

    ... so you can store const std::type_info pointers in your map:

    #include <iostream>
    #include <map>
    #include <string>
    #include <typeinfo>
    #include <utility>
    #include <variant>
    
    using data = std::variant<std::string, bool, int, float, double>;
    
    std::ostream& operator<<(std::ostream& os, const data& v) {
        switch(v.index()) {
        case 0: os << std::get<0>(v); break;
        case 1: os << std::get<1>(v); break;
        case 2: os << std::get<2>(v); break;
        case 3: os << std::get<3>(v); break;
        case 4: os << std::get<4>(v); break;
        }
        return os;
    }
    
    std::map<std::string, std::pair<const std::type_info*, data>> mProps;
    
    template<typename T>
    void add_xml_property(const std::string& name, T d) {
        if(mProps.find(name) == mProps.end()) mProps[name] = {&typeid(T), d};
    }
    
    int main() {
        add_xml_property("foo", std::string("hello"));
        add_xml_property("bar", 123);
        add_xml_property("baz", 3.14159);
    
        for(auto& [k, v] : mProps)
            std::cout << k << ": " << v.first->name() << '\n' << v.second << "\n\n";
    }
    

    Possible output:

    bar: i
    123
    
    baz: d
    3.14159
    
    foo: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
    hello