相关疑难解决方法(0)

unique_ptr,pimpl/forward声明和完整定义

我已经在这里这里检查了问题,但仍然无法弄清楚出了什么问题.

这是调用代码:

#include "lib.h"

using namespace lib;

int
main(const int argc, const char *argv[]) 
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是lib代码:

#ifndef lib_h
#define lib_h

#include <string>
#include <vector>
#include <memory>

namespace lib
{

class Foo_impl;

class Foo
{
    public:
        Foo();
        ~Foo();

    private:
        Foo(const Foo&);
        Foo& operator=(const Foo&);

        std::unique_ptr<Foo_impl> m_impl = nullptr;

        friend class Foo_impl;
};

} // namespace

#endif
Run Code Online (Sandbox Code Playgroud)

clang ++给了我这个错误:

将'sizeof'无效应用于不完整类型'lib :: Foo_impl'
注意:在成员函数'std :: default_delete :: operator()'的实例化中请求

你可以看到我已经特别声明了Foo析构函数.我还缺少什么?

c++ language-lawyer c++11

15
推荐指数
2
解决办法
2900
查看次数

在clang中,为什么这个模板默认参数需要实例化析构函数?

struct incomplete_type;

#if 0
struct incomplete_type {
    static void foo() {}
};
#endif

template<typename T>
struct problem_type
{
    constexpr problem_type(int) noexcept {};
    constexpr problem_type(double) noexcept : problem_type(5) {}

    ~problem_type() {
        T::foo();
    }
};

void bar(problem_type<incomplete_type> arg=5.0) noexcept;
Run Code Online (Sandbox Code Playgroud)

bar有一个调用转发构造函数的默认参数也是 时constexpr,编译器还会尝试实例化析构函数,但会失败,因为T::foo无法调用,因为T它是不完整类型,

如果默认参数不调用转发构造函数(例如,如果我们更改5.05),如果转发构造函数不是constexpr,或者(当然)如果类型T此时类型已完成,则不会出现此问题。

constexpr如果析构函数是,即使构造函数没有转发,也会出现该问题。

noexcept似乎无关紧要,但我将其保留下来以确保编译器不会尝试生成堆栈展开代码。

这只发生在 clang (12.0.1) 上,而不发生在 gcc (11.2) 或 Visual Studio (19.29) 上。见神箭

请注意,该函数bar 未定义或调用

为什么这不能在 clang 中编译?

c++ language-lawyer

11
推荐指数
1
解决办法
399
查看次数

析构函数必须仅可用(公共)还是对默认初始化的类成员完全有效?

请考虑一个A具有带默认初始值设定项的类型字段u的结构U<R>。析构函数~U<R>仅声明:

template<typename T>
struct U {
    ~U();
};

struct R;

struct A {
    U<R> u = U<R>{};
};
Run Code Online (Sandbox Code Playgroud)

所有编译器都接受此代码,演示: https: //gcc.godbolt.org/z/oqMjTovMo

但是如果我们将析构函数定义~U<R>如下:

template<typename T>
struct U {
    ~U() { static_assert( sizeof(T) > 0 ); }
};

Run Code Online (Sandbox Code Playgroud)

那么当前的编译器就会出现分歧。MSVC 不断接受程序,而 GCC/Clang 打印错误

error: invalid application of 'sizeof' to an incomplete type 'R'
Run Code Online (Sandbox Code Playgroud)

演示: https: //gcc.godbolt.org/z/713TzPd6v

显然,编译器必须验证默认初始化类成员的析构函数的可用性,以防在构造过程中发生异常。但标准是否要求编译器只检查析构函数的可用性(如 MSVC 所做的那样),还是编译器也应该验证其主体?RMSVC 行为在这里看起来更方便,因为它允许在结构定义时进行前向声明A

PS:这个探索不仅仅具有纯粹的理论意义。如果将U此处替换为std::unique_ptrthen ,则可以解释为什么类型的类字段std::unique_ptr<R>被 MSVC …

c++ language-lawyer incomplete-type c++20

5
推荐指数
1
解决办法
160
查看次数

标签 统计

c++ ×3

language-lawyer ×3

c++11 ×1

c++20 ×1

incomplete-type ×1