【问题标题】:is_trivially_destructible: invalid use of incomplete type ‘class Bar2’is_trivially_destructible:不完整类型“类 Bar2”的无效使用
【发布时间】:2019-12-13 07:24:57
【问题描述】:

例如我需要一些包装类,它的工作之一是告诉我容器是否is_trivially_destructible

template<typename T, typename = void>
class Foo {
 public:
  Foo(T *t) {
    std::cout << "a trivial" << std::endl;
  }
};

template<typename T>
class Foo<T, typename std::enable_if_t<!std::is_trivially_destructible<T>::value>> {
 public:
  Foo(T *t) {
    std::cout << "not a trivial" << std::endl;
  }
};

还有两个测试类:

class Bar1 {
};

class Bar2 {
 public:
  ~Bar2() {}
};

它工作正常:

int main() {
  Bar1 bar1;
  Bar2 bar2;
  Foo<Bar1> foo1(&bar1);
  Foo<Bar2> foo2(&bar2);
}

但如果测试类变得更复杂:

class Bar2 {
 public:
  Bar2() : foo(nullptr) {}
  Foo<Bar2> foo;
  ~Bar2() {}
};

我收到一个错误:

错误:不完整类型“class Bar2”的使用无效

我猜在Bar2类声明结束之前,Bar2类是不完整的,所以在Bar2的声明中访问Bar2是被禁止的。

那么这是一个错误的设计模式吗?如果没有,我该如何解决这个问题?

可以重现此问题的整个程序:

#include <iostream>


template<typename T, typename = void>
class Foo {
 public:
  Foo(T *t) {
    std::cout << "a trivial" << std::endl;
  }
};

template<typename T>
class Foo<T, typename std::enable_if_t<!std::is_trivially_destructible<T>::value>> {
 public:
  Foo(T *t) {
    std::cout << "not a trivial" << std::endl;
  }
};

class Bar1 {
};

class Bar2 {
 public:
  Bar2() : foo(nullptr) {}
  Foo<Bar2> foo;
  ~Bar2() {}
};

int main() {
  Bar1 bar1;
  Bar2 bar2;
  Foo<Bar1> foo1(&bar1);
  Foo<Bar2> foo2(&bar2);
}

【问题讨论】:

  • 您能否发布一个给出错误消息的程序,目前您有 4 个 sn-ps,尚不清楚它们是如何一起产生问题的
  • @M.M 完整程序已粘贴。
  • “我猜在 Bar2 类声明结束之前,Bar2 类是不完整的” 正确,所以你不能有成员 Foo&lt;Bar2&gt; foo;。 pimpl idiom 可能会有所帮助。

标签: c++ c++11 templates


【解决方案1】:

reference 中明确写到std::is_trivially_destructible 的类型必须是完整的:

T 应该是完整类型、(可能是 cv 限定的)void 或数组 未知的界限。否则,行为未定义。

如果上面的模板的实例依赖,直接或 间接地,在不完整的类型上,并且实例化可能会产生 如果假设完成了该类型,则会出现不同的结果, 行为未定义。

还有:

允许的未定义行为包括忽略情况 完全具有不可预测的结果,在翻译过程中表现得很好 或以文件化方式执行程序的特征 环境(无论是否发布诊断消息),以 终止翻译或执行(发出 诊断信息

所以你的程序不编译似乎没问题。

请注意,这没关系:

class Bar2 {
 public:
  Bar2();
  ~Bar2();
  Foo<Bar2>* foo;
};

Bar2::Bar2(): foo(new Foo<Bar2>(nullptr)) {}
Bar2::~Bar2() { delete foo; }

【讨论】:

  • 嗨,我的 Foo&lt;T&gt; 类有点像 std::vector 之类的容器,让它成为一个指针要么没有意义,要么 delete 会出现问题,这让我抓狂。
  • 那么也许你不应该使用enable_if,而是直接在你的类方法中使用std::is_trivially_destructible&lt;T&gt;::value;例如。对于构造函数:` Foo(T *t) { if (std::is_trivially_destructible::value) { std::cout
猜你喜欢
  • 2017-10-24
  • 2010-10-13
  • 2013-05-19
  • 2016-04-06
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多