涉及转发接口中的引用的重载

时间:2017-11-20 22:13:11

标签: c++ c++11 gcc unique-ptr

我目前正在编写一个库,它有助于延迟调用和回调注册,这些调用必须使用gcc,clang和MSVC。

我遇到了一些我觉得非常奇怪的事情。我有一个带有两个重载的函数,当且仅当在接口中定义了函数时,我才会收到错误。我使用gcc 6.3.0-18和clang 3.8.1-24得到了同样的错误。

根据Google推荐的受保护构造函数创建一个界面。

#include <queue>
#include <memory>

template <class T>
class IA {
 public:
  virtual ~IA() = default;
  // virtual bool push(const T& souce) = 0; /* Issue */
  virtual bool push(T&& source) = 0;
 protected:
  IA() = default;
};

实现接口的类

template <class T>
class A : public IA<T> {
 public:
  ~A() override {};

  bool push(const T& source) {
    m_queue.push(source);
    return true;
  }

  bool push(T&& source) {
    m_queue.push(std::move(source));
    return true;
  }
 private:
  std::queue<T> m_queue;
};

现在,如果我使用std::unique_ptr

实例化该类
int main() {
  A<std::unique_ptr<float> > a;
  return 0;
}

一切正常。除非,我从界面中取消了原型bool push(const T& soruce)的功能。然后,我得到了错误。

/usr/include/c++/6/ext/new_allocator.h:120:4: error: use of deleted 
function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const 
std::unique_ptr<_Tp, _Dp>&) [with _Tp = float; _Dp = 
std::default_delete<float>]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

我完全了解std::unique_ptr无法复制的事实,但如果该函数仅存在于实现中,为什么错误不会出现。

1 个答案:

答案 0 :(得分:3)

当您使用不可复制的类型std::unique_ptr<T>实例化模板时,编译器只会抱怨这一点。模板解析在C ++中的工作方式是通过一个名为monomorphization的过程。编译器为每个模板实例创建不同的类型。单态化完成后,A<int>A<float>无关。另一方面,这意味着编译器仅为您实际使用的类型创建这些实例。

在您的特定情况下,只要您不为T使用不可复制的类型,或者如果您使用一个并取消注释调用其复制构造函数的代码,它就会正常编译 - {{1} }。

除此之外,似乎编译器甚至无法编译第一个推送方法,因为它们能够推断它是未使用的(see live example)。这意味着它可以包含可解析但不正确的C ++代码。如果该方法是虚拟的,编译器就不能再推断它没有被使用(因为它们可以通过vtable调用),所以它必须为该方法生成代码,从而遇到错误。