C4150:删除指向不完整类型和PIMPL成语的指针

C4150: Deletion of pointer to incomplete type and PIMPL idiom

本文关键字:类型 PIMPL 成语 指针 删除 C4150      更新时间:2023-10-16

是否有任何方法可以在C 中使用模板类正确实现PIMPL成语?

例如,我有以下PIMPL类:

template <typename T> struct PrivateImplementation {
    PrivateImplementation<T>(T* impl) : implementation(impl) {
    }
    ~PrivateImplementation<T>() {
        if (implementation != nullptr) delete implementation;
    }
    PrivateImplementation<T>(const PrivateImplementation<T>& c) = delete;
    void operator=(const PrivateImplementation<T>& a) = delete;
    PrivateImplementation<T>(PrivateImplementation<T>&& m) { 
        implementation = m.implementation;
        m.implementation = nullptr;
    }
    T* operator->() const {
        return implementation;
    }
    private:
    T* implementation;
};

但是,当我像下面一样使用它时,编译器抱怨(警告)我要删除不完整的类型:

logger.h

class LoggerStream {
    public:
    LoggerStream(std::wstring componentName);
    ~LoggerStream();
    LoggerStream(const LoggerStream&) = delete;
    void operator=(const LoggerStream&) = delete;
    LoggerStream(LoggerStream&&);
    void Write(std::wstring message, const char* __function__, const char* __file__, int __line__) const;
    void Write(std::wstring message) const;
    private:
    struct LoggerStreamImpl;
    PrivateImplementation<LoggerStreamImpl> impl;
};

logger.cpp

struct LoggerStream::LoggerStreamImpl {
    LoggerStreamImpl(std::wstring componentName) : componentName(componentName) { }
    ~LoggerStreamImpl() = default;
    LoggerStreamImpl(const LoggerStreamImpl&) = delete;
    void operator=(const LoggerStreamImpl&) = delete;
    LoggerStreamImpl(LoggerStreamImpl&&);
    const std::wstring componentName;
};
LoggerStream::LoggerStream(std::wstring componentName)
    : impl(new LoggerStreamImpl { componentName }) { }
LoggerStream::~LoggerStream() { }
void LoggerStream::Write(std::wstring message, const char* __function__, const char* __file__, int __line__) const {
    // Some implementation
}
void LoggerStream::Write(std::wstring message) const {
    // Some implementation
}

我显然在.cpp中的LoggerStreamImpl有一个定义的破坏者,那么什么给出了?

谢谢。

当我存储一个std :: unique_ptr时,我不希望完全可见的类型,例如pimpl,我使用一个自定义deleter,其中operator()在CPP中定义了cpp,班级可见。

它可以解决问题,并且通过链接时间优化,即使介绍的函数调用间接也可以优化,如果编译器认为它是相关的。

包含Logger.h的任何文件都尝试编译自身的模板。因此,可以说您有一个包含int main()(或其他输入点)的main.cpp文件,该文件包括Logger.h。main.cpp将看到logger.h,尝试对其进行解析,在解析它的过程中,它将尝试编译T = LoggerStreamImplPrivateImplementation模板的版本。如果您的编译器为C 11符合C 11,并且可以告诉您私人完成是外部定义的。