是否可以在没有编译失败的情况下推断类型是否不完整? [复制]

Posted

技术标签:

【中文标题】是否可以在没有编译失败的情况下推断类型是否不完整? [复制]【英文标题】:Is it possible to deduce whether type is incomplete without compilation failure? [duplicate] 【发布时间】:2012-01-16 22:54:51 【问题描述】:

我想实现像 sizeof(complete_type) 将返回实际 sizeof 和 sizeof(incomplete_type) - 将只是 0 的行为

我需要它来为 IPC(进程间)通信提供扩展的运行时类型信息,每个类型都有描述结构:

struct my_type_info

    bool   is_pointer;
    size_t size;         //for double* will be 4 on i386. that is sizeof(double*)
    size_t base_size;    //for double* will be 8. that is sizeof(double)
;

当进入我的系统时出现问题,例如 class MyOnlyDeclaredClass;我得到了编译错误,显然是因为我无法确定它的大小。

boost type_traits http://www.boost.org/doc/libs/1_48_0/libs/type_traits/doc/html/index.html 建议许多编译时类,但没有'is_incomplete'

有趣的编译器是 VS2008、VS2010、clang 3、gcc-4.6、gcc-4.7

【问题讨论】:

如果检测到类型不完整怎么办?抛出 static_assert 错误? 不,如果指针位于共享内存中,我可以将它传递给另一个进程而不知道它是什么类型。指针可以通过从其值中减去共享内存基数来轻松传递。 我好像还是没看懂。为什么不以这种方式传递所有指针(包括完整类型和不完整类型)? 因为在我的系统中提供了另一种指针——比如应该以另一种方式传递给另一个进程的接口。此外,它将允许在运行时检查指针来自哪种内存。我承认有能力以另一种不太优雅的方式解决任务。 请告诉我们更多您真正需要做的事情。 【参考方案1】:

不要尝试这样做。

从根本上说是不健全的。模板是按类型参数化的,而不是实例化点。类类型不完整或本身不完整,它在翻译过程中的某个时间点是完整的。

在某些类型上实例化的模板在每个实例化中必须具有完全相同的语义。

如果没有,行为未定义。

【讨论】:

+1。我也快要那样尖叫了。 while 的想法从根本上被打破了。 好吧,我实际上有一个合理有效的用例。我一直在做一个小包装生成器工具,将 C++ 函数导出到其他语言,我决定不尝试解析 C++,而是使用可变参数模板将函数声明分开。在其中一些情况下,我现在使用 is_complete 来检查某些类是否是“按要求”派生的,如果包装工具不知道这些类,则假设它们是派生的。如果类不符合规范,编译 C++ 无论如何都会失败;如果该工具已经可以进行检查,它只会提前失败。【参考方案2】:

像往常一样使用SFINAE。这是一种可能的实现方式:

struct char256  char x[256]; ;

template <typename T>
char256 is_complete_helper(int(*)[sizeof(T)]);

template <typename>
char is_complete_helper(...);

template <typename T>
struct is_complete

    enum  value = sizeof(is_complete_helper<T>(0)) != 1 ;
;

例子:

#include <cstdio>

struct F;
struct G ;

int main()

    printf("%d %d\n", is_complete<F>::value, is_complete<G>::value);
    return 0;

(注意:适用于gcc 4.5(不是因为C++0x)和clang 2.9,but not gcc 4.3)

【讨论】:

顺便说一句,这是boost::checked_delete中使用的技巧。 哇!我以前不能这样想。 测试结果:VS2008/VS2010(都带有 SP1):错误 C2027 使用未定义的类型“F”。 g++-4.7 - 工作,clang - 工作与警告。 struct T; int i=(cout&lt;&lt;is_complete&lt;T&gt;::value,i); struct T; int j=(cout&lt;&lt;is_complete&lt;T&gt;::value,i); 哈哈 00 by fact (clang 3 -std=c++0x) :( 记住生成的实例......效果 boost::shared_ptr 用来记住完成的类型,允许在不可见的情况下删除它类型标题。

以上是关于是否可以在没有编译失败的情况下推断类型是否不完整? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

我可以在编译器指令中推断出类型的类型吗

是否可以在不使用插件的情况下配置 maven 来编译生成的源代码?

如何在不依赖类型推断的情况下排除无意义的类型?

从完整日期开始推断

session timer

是否可以在 WCF 中没有无参数构造函数的情况下序列化对象?