Template undefined reference on windows with MinGW 4.8

287 views Asked by At

I am using static template members in a class; the templates are instantiated in a cpp built in a software. I have a plug-in for the software that uses the name() template method in the header, but does not build the source file which contains the instantiation. The build works on Linux with g++-4.9 but fails on MinGW 4.8. I want to know how to make it work with the almost same compiler, but on Windows instead.

.hpp :

enum class ToplevelMenuElement
{
    FileMenu, 
    ...
    AboutMenu
};

enum class FileMenuElement
{
    New,
    ... ,
    Quit
};

// Others menus macros are defined

class MenuInterface
{
    public:
        template<typename MenuType>
        static QString name(MenuType elt);

    private:
        static const std::map<ToplevelMenuElement, QString> m_map;
        static const std::map<FileMenuElement, QString> m_fileMap;
};

.cpp :

template<>
QString MenuInterface::name(ToplevelMenuElement elt)
{
    return m_map.at(elt);
}

template<>
QString MenuInterface::name(FileMenuElement elt)
{
    return m_fileMap.at(elt);
}

const std::map<ToplevelMenuElement, QString> MenuInterface::m_map
{
    {ToplevelMenuElement::FileMenu, QObject::tr("File")},
    ...
    {ToplevelMenuElement::AboutMenu, QObject::tr("About")}
};

const std::map<FileMenuElement, QString> MenuInterface::m_fileMap
{
    {FileMenuElement::New, QObject::tr("New")},
    ..., 
    {FileMenuElement::Quit, QObject::tr("Quit")}
};

Error :

undefined reference to `QString MenuInterface::name<ToplevelMenuElement>(ToplevelMenuElement)'

Is there any flag to use to make some kind of lazy instantiation ? Or should I build the .cpp containing the template instantiation in my plug-in ?

2

There are 2 answers

2
ravi On

This has been asked many times...declaration and definitions for templates should be same file.

3
David G On

Because you are linking a source file that contains explicit specializations, you need to declare your explicit specializations before you define them. From §14.7.3/3:

A declaration of a function template, class template, or variable template being explicitly specialized shall precede the declaration of the explicit specialization. [ Note: A declaration, but not a definition of the template is required. — end note ]

So you need to put these after your class in your header file:

template<>
QString MenuInterface::name(ToplevelMenuElement elt);

template<>
QString MenuInterface::name(FileMenuElement elt);