dvilela
dvilela

Reputation: 1262

Is it possible to have a common, not-specialized, static member in a class template in C++?

Let's say I have a class template that I want to instantiate according to a variable in a json configuration file I have loaded. In that json file, a variable would say: "TYPEA" or "TYPEB".

Also, I have an enum that stores all possible types so I can switch-case to intantiate one specialization or another. Now I need a std::map that correlates this enum with the correspondent value in the config file, something like: {"TYPEA" = TYPEA, "TYPEB" = TYPEB}.

After I have the loaded string, I want to check whether it is a valid value, so I look up the map and, if the key does not exist, I throw an exception. If the key exists, I switch-case through the enum and instantiate the appropriate template specialization.

All this means I have a static std::map, common to all specializations. Is this possible, or is a stupid way of doing this? Should it be defined in the header or a tpp file? There is trouble with the map definition.

#include <iostream>
#include <map>

template <typename T>
class A
{
    public:

        T m_t;
        enum classType{TYPEA, TYPEB, TYPEC};
        static std::map<std::string, classType> m_typeMap;
        classType m_type;

        A(T& t) : m_t(t) {}
};


template <typename T>
std::map<std::string, A<T>::classType> A<T>::m_typeMap =   // here I get the error
{{"TYPEA", A::classType::TYPEA},
 {"TYPEB", A::classType::TYPEB},
 {"TYPEC", A::classType::TYPEC}};


int main()
{
    std::cout << A::m_typeMap["TYPEA"] << std::endl;
}

The compiler error is:

../main.cpp:19:38: error: type/value mismatch at argument 2 in template parameter list for 'template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map'
 std::map<std::string, A<T>::classType> A<T>::m_typeMap =
                                      ^
../main.cpp:19:38: note:   expected a type, got 'A<T>::classType'
../main.cpp:19:38: error: template argument 4 is invalid
../main.cpp:19:46: error: conflicting declaration 'int A<T>::m_typeMap'
 std::map<std::string, A<T>::classType> A<T>::m_typeMap =
                                              ^~~~~~~~~
../main.cpp:11:49: note: previous declaration as 'std::map<std::__cxx11::basic_string<char>, A<T>::classType> A<T>::m_typeMap'
         static std::map<std::string, classType> m_typeMap;
                                                 ^~~~~~~~~
../main.cpp:19:46: error: declaration of 'std::map<std::__cxx11::basic_string<char>, A<T>::classType> A<T>::m_typeMap' outside of class is not definition [-fpermissive]
 std::map<std::string, A<T>::classType> A<T>::m_typeMap =
                                              ^~~~~~~~~
../main.cpp: In function 'int main()':
../main.cpp:27:18: error: 'template<class T> class A' used without template parameters
     std::cout << A::m_typeMap["TYPEA"] << std::endl;

Upvotes: 2

Views: 96

Answers (1)

Ted Lyngmo
Ted Lyngmo

Reputation: 117298

Is it possible to have a common, not-specialized, static member in a template class in C++?

Make that "class template" and it becomes easier to understand what it actually is.

It's certainly possible if you make the class template inherit from a common base.

struct base { // non-template base
    // static functions and variables 
};

template<typename T>
class Foo : public base {}

Upvotes: 3

Related Questions