【问题标题】:C++ using template type with unordered mapC++ 使用具有无序映射的模板类型
【发布时间】:2021-12-30 19:05:50
【问题描述】:

我是 C++ 新手,所以这可能是一个简单的错误,但是这段代码现在给我带来了几个小时的问题。我真的只是不确定下一步该尝试什么。

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;
}

错误:

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>        ]

我正在尝试创建一个 hashmap 作为键类型为 T、值类型为 unsigned int 的成员变量,并且我正在将 boost 库用于哈希函数。

【问题讨论】:

  • 1.您忘记了每个方法定义之前的template&lt;class T&gt;。 2 Why can templates only be implemented in the header file?.
  • 来自 MSVC 的错误消息在这里真的没有帮助。似乎假设您正在尝试显式专业化,但其语法也会有所不同。它应该只是在尝试定义 EratosthenesHashMap::EratosthenesHashMap 时失败并出现语法错误。
  • @user17732522, 由于class T 是声明类内联的合法方式,编译器可能采用EratosthenesHashMap&lt;class T&gt;,精确地实例化模板因为这种语法不能是专业化或任何东西,因此使用std::pairstd::unordered_map,然后最终看到包含不完整类作为成员的一对将不起作用。错误本身对我来说很有意义,它只有几层深。甚至可能是编译器看到 EratosthenesHashMap&lt;class T&gt; 并回退到“这必须以 ... 类型开始声明”。
  • @chris 这可能是一种解释,但 MSVC 只接受没有 template&lt;&gt; 介绍的显式特化。如果您将 class T 更改为 T 您会得到相同的错误,并且使用 int 而不是 T 它可以愉快地编译。
  • @user17732522,很有趣。在那种情况下,我撤销我所说的话。这似乎是一个令人高兴的巧合,它符合这种逻辑。

标签: c++


【解决方案1】:

在头文件和 .cpp 文件之间拆分模板类并且易于调用者使用是相当困难的。相反,将整个模板类内联到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;
};

【讨论】:

    【解决方案2】:

    定义模板类成员的方式是

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

    除此之外,您可能应该在头文件中定义模板,否则它们将只能在同一个 cpp 文件中使用。

    Why can templates only be implemented in the header file?

    【讨论】:

    • 对,剪得太多了……
    【解决方案3】:

    您的代码无法编译的原因是您无法以典型方式将类模板分解为 .h 文件和 .cpp 文件。

    假设您有一个使用 EratosthenesHashMap&lt;int&gt; 的 main.cpp 文件,并且您在问题中将 EratosthenesHashMap 分解为 .h 和 .cpp,然后 main.cpp 完全独立于 EratosthenesHashMap.cpp 进行编译,并且需要能够链接到 EratosthenesHashMap&lt;int&gt; 的实现,但 EratosthenesHashMap.cpp 不知道它将应用于什么类型,所以这是不可能的。

    EratosthenesHashMap.cpp 没有定义一个类;它定义了一个模板;它不能被编译成可以链接的目标文件。

    出于这个原因,通常您通过在标头中提供完整实现来使用模板。

    【讨论】:

      猜你喜欢
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 2018-12-21
      相关资源
      最近更新 更多