【问题标题】:Incomplete declaration of a partially specialized template部分特化模板的不完整声明
【发布时间】:2016-06-09 09:05:34
【问题描述】:

我正在尝试为我自己的类TestHandle 部分专门化std::hash 结构,并且这个类的实现使用不透明指针习语进行了拆分。所以我试图为impl 类提供自己的std::hash 专业化。但我遇到了模板问题。

有人可以帮我理解为什么会这样吗?我在下面附上了所有必要的代码。

TestHandle.h

#pragma once
#include <memory>

class TestHandle {
public:
    TestHandle();

    void print();

    class Impl;
    std::unique_ptr<Impl> implementation;
};

TestHandle.cpp

#include "TestHandle.h"
#include "Impl.h"
#include <iostream>
using std::cout;
using std::endl;

TestHandle::TestHandle() : implementation{new TestHandle::Impl} { }

void TestHandle::print() {
    this->implementation->print();
    cout << "Hash of this->implementation is " 
        << std::hash<TestHandle::Impl>()(*this->implementation) << endl;
}

Impl.h

#pragma once
#include "TestHandle.h"
#include <functional>

class TestHandle::Impl {
public:

    void print();
    int inner_integer;
};

namespace std {
    template <> struct std::hash<TestHandle::Impl>;
}

Impl.cpp

#include "TestHandle.h"
#include "Impl.h"
#include <iostream>
using std::cout;
using std::endl;
#include <functional>

namespace std {
    template <> struct hash <TestHandle::Impl> {
        size_t operator() (const TestHandle::Impl& implementation) {
            return std::hash<int>()(implementation.inner_integer);
        }
    };
}

void TestHandle::Impl::print() {
    cout << "Printing from impl" << endl;
}

我正在使用以下命令进行编译

g++ -std=c++14 -c Impl.cpp TestHandle.cpp

我收到以下错误

TestHandle.cpp:11:12: error: invalid use of incomplete type 'std::hash<TestHandle::Impl>'
<< std::hash<TestHandle::Impl>()(*this->implementation) << endl; 

【问题讨论】:

  • 你应该在尝试特殊std::hash iirc之前包含&lt;functional&gt;,这是定义主模板的地方
  • 谢谢!我会更新我的帖子
  • 另一个问题是,模板在使用它的编译单元之一中不可见。 TestHandle.cpp 需要看实现,但是hte 实现在impl.cpp。所以你应该将实现移到标题中。
  • 但是因为它是一个特化,所以不能将其视为函数调用吗?如果我在两个文件中分开了一个函数调用,这会运行好吗?
  • 是的,如果它只是一个函数调用,就可以了,但是对于模板,没有。您可以转发声明一个小辅助函数,并使模板std::hash 方法operator() 调用辅助函数,并在单个编译单元中实现辅助函数。那没关系。但是当一个模板被实例化时,在任何编译单元中,定义都需要可见,否则实例化就无法工作。

标签: c++ templates c++11 hash c++14


【解决方案1】:
template <> struct std::hash<TestHandle::Impl>;

只需 forward 声明专业化。它不必实现原始模板的所有方法(或任何方法)。编译器不知道operator()

您需要定义struct(代替声明);

template <> struct hash <TestHandle::Impl> {
        size_t operator() (const TestHandle::Impl& implementation) const noexcept;
    };

附注:您还需要提供&lt;functional&gt; 的主要模板(通过包含)(原始列出的代码中缺少)。

【讨论】:

  • 应该没问题,但定义需要可见。
  • 我该怎么做呢?如果我有一个函数声明和定义,这很好......我想将实现与模块分开
猜你喜欢
  • 1970-01-01
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 2013-06-16
  • 2011-10-30
  • 1970-01-01
相关资源
最近更新 更多