简体   繁体   中英

std::map holding any value type

Code:

#include <iostream>
#include<map>
using namespace std;

class MyClass {

public:

    class MyFieldInterface
    {
      public:
        int m_Size;
        ~MyFieldInterface() = default;
    };

    template <typename T>
    class MyField : public MyFieldInterface {
      public:
           MyField(T val) {m_Value = val;}
           T m_Value; 
    };

    template <typename T>
    MyField<T>* getType(int type, T val) {
       if (type == 0) return new MyField<int>(val);
       if (type == 1) return new MyField<double>(val);
       if (type == 2) return new MyField<char>(val);
    }

    map<string, MyFieldInterface* > fields;  
};

int main()
{
    MyClass obj;

    obj.fields["a"] = obj.getType<int>(0, 1);
    obj.fields["b"] = obj.getType<double>(1, 1.1);
    obj.fields["c"] = obj.getType<char>(2, 'a');

    return 0;
}

Question:

I want std::map to hold any value type, thus I created a template class with dynamic inheritance. I have defined template class inside MyClass for the reason I don't want its definition to be exposed to user. Using getType function I will create a new object with given type which will be stored into the map.

With the above approach I get the below errors, I'm not able to succeed with the above approach.

main.cpp: In instantiation of ‘MyClass::MyField<T>* MyClass::getType(int, T) [with T = int]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',45)">main.cpp:45:44</span>:   required from here
main.cpp:34:53: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
        if (type == 1) return new MyField<double>(val);
                                                     ^
main.cpp:35:51: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
        if (type == 2) return new MyField<char>(val);
                                                   ^
main.cpp: In instantiation of ‘MyClass::MyField<T>* MyClass::getType(int, T) [with T = double]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',46)">main.cpp:46:49</span>:   required from here
main.cpp:33:50: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
        if (type == 0) return new MyField<int>(val);
                                                  ^
main.cpp:35:51: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
        if (type == 2) return new MyField<char>(val);
                                                   ^
main.cpp: In instantiation of ‘MyClass::MyField<T>* MyClass::getType(int, T) [with T = char]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',47)">main.cpp:47:47</span>:   required from here
main.cpp:33:50: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
        if (type == 0) return new MyField<int>(val);
                                                  ^
main.cpp:34:53: error: cannot convert ‘MyClass::MyField*’ to ‘MyClass::MyField*’ in return
        if (type == 1) return new MyField<double>(val);
                                                     ^

You can't use a run-time parameter to choose between multiple types. You need to decide what type is returned at compile time. But this is exactly what templates are for, so you could simply do:

template <typename T>
MyField<T>* getType(T val) {
   return new MyField<T>(val);
}

and then use the function like this:

obj.fields["a"] = obj.getType(1);
obj.fields["b"] = obj.getType(1.1);
obj.fields["c"] = obj.getType('a');

Note that you don't need to specify T at the call site, since that can be deduced from the function argument.

Of course, you will need to keep track of what type each key in the map refers to separately.

Here's a demo .

Also, the way this function is implemented, the name getType is confusing, since you are not actually returning a type here. Perhaps a better name would be getAnyPointer .

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