C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 将函数标记为虚拟导致编译器错误与unique_ptr大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个包含矢量的模板类.我试在这个类中存储unique_ptrs,它工作正常.但是,当我将void add(const T& elem)函数标记为虚拟时,我的编译器(clang)告诉我,我正在为unique_ptr进行“调用隐式删除的复制构造函数”.

我知道unique_ptrs无法复制,因此我创建了void add(T&& elem)函数.我只是不知道为什么将其他添加函数标记为虚拟导致编译器错误.

谢谢你的时间.

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

template <typename T>
class ContainerWrapper {
private:
    vector<T> vec;
public:
    ContainerWrapper() : vec() {

    }

    //Marking this as virtual causes a compiler error
    void add(const T& elem) {
        vec.push_BACk(elem);
    }

    void add(T&& elem) {
        vec.push_BACk(std::move(elem));
    }

    T removeLast() {
        T last = std::move(vec.BACk());
        vec.pop_BACk();
        return last;
    }
};

int main() {
    ContainerWrapper<unique_ptr<String>> w;
    w.add(unique_ptr<String>(new String("Hello")));

    unique_ptr<String> s = w.removeLast();

    cout << *s << endl;
}

解决方法

这里的问题是std :: unique_ptr的拷贝构造函数标记为= delete.这意味着在使用std :: unique_ptr调用时,add(T const&)重载成员函数内的vec.push_BACk(elem)调用将无法编译.一旦成员函数被实例化,编译器就会意识到这一点.

Standard在14.7.1隐式实例化[temp.inst]中有2个相关引用:

第6条规定 – 没有虚拟关键字 – 允许编译器但不要求实例化add(T const&)和add(T&&)以便解决哪个过载是最佳匹配. gcc 4.7.2和Clang 3.2都不需要实例化,因为它们恰好推断出rvalue引用总是比临时引用更适合临时.

第10条规定 – 即使使用virtual关键字 – 也允许编译器但不需要实例化add(T const&)和add(T&&)以便解决哪个重载是最佳匹配. gcc 4.7.2和Clang 3.2都碰巧实例化了两个成员函数,即使它们都可以推断出左值超载永远不会是更好的匹配.

请注意,如果您使ContainerWrapper成为具有嵌套typedef的常规类unique_ptr< String> T;,然后gcc和Clang都会生成带或不带virtual关键字的错误,因为它们必须为两个成员函数生成代码.这不会是SFINAE,因为在替换推断的参数期间不会发生错误.

结论:这不是一个错误,而是一个实施质量问题.

大佬总结

以上是大佬教程为你收集整理的c – 将函数标记为虚拟导致编译器错误与unique_ptr全部内容,希望文章能够帮你解决c – 将函数标记为虚拟导致编译器错误与unique_ptr所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。