我目前正在编写一个库,它有助于延迟调用和回调注册,这些调用必须使用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
无法复制的事实,但如果该函数仅存在于实现中,为什么错误不会出现。
答案 0 :(得分:3)
当您使用不可复制的类型std::unique_ptr<T>
实例化模板时,编译器只会抱怨这一点。模板解析在C ++中的工作方式是通过一个名为monomorphization的过程。编译器为每个模板实例创建不同的类型。单态化完成后,A<int>
和A<float>
无关。另一方面,这意味着编译器仅为您实际使用的类型创建这些实例。
在您的特定情况下,只要您不为T
使用不可复制的类型,或者如果您使用一个并取消注释调用其复制构造函数的代码,它就会正常编译 - {{1} }。
除此之外,似乎编译器甚至无法编译第一个推送方法,因为它们能够推断它是未使用的(see live example)。这意味着它可以包含可解析但不正确的C ++代码。如果该方法是虚拟的,编译器就不能再推断它没有被使用(因为它们可以通过vtable调用),所以它必须为该方法生成代码,从而遇到错误。