Home > Mobile >  C using template type with unordered map
C using template type with unordered map

Time:12-31

I am new to C so this is likely a simple mistake but this code is giving me problems for hours now. I am really just not sure what to try next.

EratosthenesHashMap.h

#pragma once

#include <unordered_map>
#include <boost/functional/hash.hpp>
#include "SieveOfEratosthenes.h"

template<class T>
class EratosthenesHashMap
{

public:
    EratosthenesHashMap(SieveOfEratosthenes& sieve);
    ~EratosthenesHashMap();

    unsigned int addValue(T& value);
    unsigned int getPrime(T& value) const;

private:
    SieveOfEratosthenes *sieve;
    std::unordered_map<T, unsigned int, boost::hash<T>> valueMap;
};

EratosthenesHashMap.cpp

#include "EratosthenesHashMap.h"

EratosthenesHashMap<class T>::EratosthenesHashMap(SieveOfEratosthenes& sieve) 
{
    this->sieve = &sieve;
};

unsigned int EratosthenesHashMap<T>::addValue(T& value)
{
    return 0;
}

unsigned int EratosthenesHashMap<T>::getPrime(T& value) const
{
    return 0;
}

Error:

EratosthenesHashMap.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\utility(331,10): error C2079: 'std::pair<const T,unsigned int>::first' uses undefined class 'T'
1>        with
1>        [
1>            T=T
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xhash(305): message : see reference to class template instantiation 'std::pair<const T,unsigned int>' being compiled
1>        with
1>        [
1>            T=T
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xhash(304): message : while compiling class template member function 'void std::_Hash_vec<std::allocator<std::_List_unchecked_iterator<std::_List_val<std::_List_simple_types<_Ty>>>>>::_Tidy(void) noexcept'
1>        with
1>        [
1>            _Ty=std::pair<const T,unsigned int>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xhash(313): message : see reference to function template instantiation 'void std::_Hash_vec<std::allocator<std::_List_unchecked_iterator<std::_List_val<std::_List_simple_types<_Ty>>>>>::_Tidy(void) noexcept' being compiled
1>        with
1>        [
1>            _Ty=std::pair<const T,unsigned int>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xhash(1933): message : see reference to class template instantiation 'std::_Hash_vec<std::allocator<std::_List_unchecked_iterator<std::_List_val<std::_List_simple_types<_Ty>>>>>' being compiled
1>        with
1>        [
1>            _Ty=std::pair<const T,unsigned int>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\unordered_map(69): message : see reference to class template instantiation 'std::_Hash<std::_Umap_traits<_Kty,_Ty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>' being compiled
1>        with
1>        [
1>            _Kty=T,
1>            _Ty=unsigned int,
1>            _Hasher=boost::hash<T>,
1>            _Keyeq=std::equal_to<T>,
1>            _Alloc=std::allocator<std::pair<const T,unsigned int>>
1>        ]
1>C:\Users\jpsie\source\repos\EratosthenesContainer\EratosthenesContainer\EratosthenesHashMap.h(20): message : see reference to class template instantiation 'std::unordered_map<T,unsigned int,boost::hash<T>,std::equal_to<T>,std::allocator<std::pair<const T,unsigned int>>>' being compiled
1>        with
1>        [
1>            T=T
1>        ]

I am trying to create a hashmap as a member variable with key type T, value type unsigned int, and I am using the boost library for a hash function.

CodePudding user response:

It is rather difficult to have a template class split between header file and .cpp file and be easy to consume by callers. Instead, inline your entire template class in EratosthenesHashMap.h:

template<class T>
class EratosthenesHashMap
{

public:
    EratosthenesHashMap(SieveOfEratosthenes& sieve)
    {
        this->sieve = &sieve;
    }
    ~EratosthenesHashMap()
    {
    }

    unsigned int addValue(T& value)
    {
        return 0;
    }

    unsigned int getPrime(T& value) const
    {
        return 0;
    }

private:
    SieveOfEratosthenes* sieve;
    std::unordered_map<T, unsigned int, boost::hash<T>> valueMap;
};

CodePudding user response:

The way to define a member of a template class is

template<class T>
EratosthenesHashMap<T>::EratosthenesHashMap(SieveOfEratosthenes& sieve) 
{
    this->sieve = &sieve;
};

On top of that, you should probably defined the templates in the header file, because otherwise they will only be usable in the same cpp file.

See Why can templates only be implemented in the header file?

CodePudding user response:

The reason your code doesn't compile is that you can't break a class template into a .h file and .cpp file in the typical way.

Say you have a main.cpp file that uses EratosthenesHashMap<int> and you have EratosthenesHashMap broken into a .h and a .cpp as in your question, then main.cpp gets compiled completely independently of EratosthenesHashMap.cpp and needs to be able to link to an implementation of EratosthenesHashMap<int> but EratosthenesHashMap.cpp does not know anything about what types it will be applied to so this is impossible.

EratosthenesHashMap.cpp does not define a class; it defines a template; it can't be compiled into an object file that can be linked against.

Typically you use templates by providing a full implementation in a header for this reason.

  •  Tags:  
  • c
  • Related