Explicit template specialization in g++ causing tr

2019-09-10 11:07发布

问题:

I've got the problem converting this piece of code to g++ from MSVC:

#include <unordered_map>
class A
{
    template <class T> class B;

    template<>
    class A::B<int>
    {

    };

    std::unordered_map<int, long, B<int>> m_Map;
};

Sure thing this is not standard c++, while VS still allows it GCC (g++) throws an error "Explicit specialization in non-namespace scope". Now I make it c++ compliant following the reference http://en.cppreference.com/w/cpp/language/template_specialization:

#include <unordered_map>

class A
{
    template <class T> class B;
    template <> class B<int>;
    std::unordered_map<int, long, B<int>> m_Map;
};

template<>
class A::B<int>
{
    std::size_t operator()(int const& n) const {
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    return 0;
}

Alas, now VS gives me an error

Error   3   error C2079: 'std::_Hash_oper1<true,_Hasher>::_Hashobj' uses undefined class 'A::B<int>'    c:\program files (x86)\microsoft visual studio 12.0\vc\include\xhash

and

 Error  2   error C2139: 'A::B<int>' : an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_empty'   c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits

So, unordered map definetely doesn't want to work with what it consideres an "undefined class". Even though I forward-declared it. Does anyone has a clue what is it all about? Thank you.

回答1:

Standard library containers can't be declared with incomplete types as the contained types. This causes undefined behaviour with no diagnostic required (meaning that some compilers may appear to accept it, and some may reject it or behave strangely at runtime).

You'll have to use a hash table from a different library (e.g.boost) that does support incomplete type, or redesign the code.

A simple fix would be to make class B not be declared within A in the first place



标签: c++ c++11 gcc g++