`
gaofen100
  • 浏览: 1180127 次
文章分类
社区版块
存档分类
最新评论

CPP POD

 
阅读更多

From: http://blog.csdn.net/aladdina/archive/2009/03/03/3953552.aspx

上午 Randy同学碰到了一个 array中应用 tr1::is_pod导致的编译错误,看了一下,顺便了解了一些概念:

在开始之前,还是说说什么是 tr1

TR1 ,全称是“ C++ Technical Report 1”,实际上是 C++标准扩展库 ISO/IEC TR 19768的一个俗称,是进入 C++标准库的一个提案。 TR1中包括的内容主要有:正则表达式 (regular expressions)、智能指针 (smart pointers),哈希表 (hash tables)以及随机数产生器 (random number generators),还包括函数对象 (Function Objects),元编程和类型属性 (Metaprogramming and Type Traits)等等很多内容。 TR1本身并不是 C++标准,而是一个草案。但是绝大多数情况下提案的内容都会成为下一个官方标准。

参见 :

http://en.wikipedia.org/wiki/Technical_Report_1

下面说说我们使用 is_pod相关的东西。

POD : 全称是“ Plain Old Data”,是 C++ 98标准 (ISO/IEC 14882, first edition, 1998-09-01)中引入的一个概念,主要目的是兼容 C C++语言中对数据的比较。实质上 POD类型主要包括 int, char, float等原始类型及其集合类型 (aggregate class)

参见:

http://en.wikipedia.org/wiki/Plain_Old_Data_Structures

http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html

POD Aggregate Class: 上面刚提到,就是一个只包含 POD 数据的类,不使用 C++ 中的封装和面向对象的特性。其中还包含的意思是说, POD 的定义是可以迭代的,如果一个类只包含 POD 数据,那这个类就属于 POD 。以此类推,如果一个类只包含 POD 数据或者 POD 类,那它也属于 POD

最后在说到 is_pod之前,说说 Randy同学碰到的编译错误:

error C2139: an undefined class is not allowed as an argument to compiler intrinsic type trait '__has_trivial_constructor'

Trivial Constructor:我们经常可以有看到 trivial之类的词,到底是什么意思呢?如果去查词典,估计很难理解。个人的理解,就是轻量级的,类似于“浅拷贝”中的“浅”,或许是更浅的浅。 Trivial Constructor其实是说更本不允许用户自己定义 constructor,即使自己定义的 constructor是一个空函数都不行。当然,定义虚函数也不行,因为虚函数会导致编译器自动生成的 constructor中 包含额外的操作。(这里trivial constructor也是个人不太明确的问题,本意应该是说更本没有constructor,但是MSDN的定义 是:__has_trivial_constructor(type): Returns true if the type has a trivial, compiler-generated constructor。因此个人觉得可以理解成,没有constructor,但是不能阻止编译器在实现的时候有自定义的设置)

最后终于说到 is_pod了,因为使用的是 MS的编译器,因此看看 MSDN中的解释:

An instance of the type predicate holds true if the type Ty is a scalar type, a POD aggregate type, or a cv-qualified form of one of them, or an array of such a type, otherwise it holds false.

其中还有一个概念“ cv-qualified”,看到不同的地方有很多争议,个人觉得这个其实很简单,就是是否可以用 const或者 volatile修饰。如果可以则是 cv-qualified,否则是 cv-unqualified。那么你可能会问,还有什么变量不能用 const或者 volatile来修饰呢?请在下面的例子中查找答案。

因此,最后,希望大家可以理解 MSDN中那么短短的一句话。

(额外说明:不同的编译器对于 is_pod的实现不一定是相同的,这里是用 Visual Studio 2008 SP1的编译器来测试的,而且 boost中的实现也针对编译器的不同做了不同的定义)

下面有 12个实例来说明

#include <iostream>

#include <type_traits>

// === 属于 POD 的对象 ===

// 没有定义任何数据成员

class pod_yes_1 {};

// 定义了一个元数据类型的公有成员变量

class pod_yes_2 { public : int a ; };

// 定义了一个元数据类型以及一个 POD 对象

class pod_yes_3 { public : float a ; pod_yes_2 b ; };

// 定义了 1 POD 对象以及一个迭代的 POD 对象

class pod_yes_4 { public : float a ; pod_yes_2 b ; pod_yes_3 c ; };

// === 不属于 POD 的对象 ===

// 从一个 POD 对象派生

class pod_no_1 : public pod_yes_1 {};

class pod_no_2 : public pod_yes_2 {};

// 虚拟继承,更不行了,而且不符合 "trivial constructor" 的要求

class pod_no_3 : virtual public pod_yes_1 {};

// 定义了一个私有(或者保护)类型的成员变量

class pod_no_4 { int a ; };

// 定义了构造函数,虽然是空的,仍然不符合 "trivial constructor" 的要求

class pod_no_5 { public : pod_no_5 (){} };

// 定义了虚函数,不符合 "trivial constructor" 的要求

class pod_no_6 { public : virtual void foo (){} };

// 父类定义了构造函数:不符合 "trivial constructor" 的要求

class pod_no_7 : public pod_no_5 {};

// PodRef 不是 cv-qualified 的对象,看到这里知道上面问题的答案了吧。也意味着不符合 "trivial constructor" 的要求。

// warning C4510: 'pod_no_8' : default constructor could not be generated

// warning C4512: 'pod_no_8' : assignment operator could not be generated

// warning C4610: class 'pod_no_8' can never be instantiated - user defined constructor required

typedef pod_yes_1 & PodRef ;

class pod_no_8 { public : PodRef x ;};

template < typename T1 >

class testpod {

public :

testpod (){

std :: cout << typeid ( T1 ). name ()<< "/tPOD: " <<( std :: tr1 :: is_pod < T1 >:: value ? "yes" : "no " );

std :: cout << "/tTrivial Constructor: " <<( __has_trivial_constructor ( T1 )? "yes" : "no" )<< std :: endl ;

}

};

void main ()

{

testpod < pod_yes_1 >();

testpod < pod_yes_2 >();

testpod < pod_yes_3 >();

testpod < pod_yes_4 >();

testpod < pod_no_1 >();

testpod < pod_no_2 >();

testpod < pod_no_3 >();

testpod < pod_no_4 >();

testpod < pod_no_5 >();

testpod < pod_no_6 >();

testpod < pod_no_7 >();

testpod < pod_no_8 >();

pod_yes_1 pod1 ;

const PodRef r1 = pod1 ; // warning C4181: qualifier applied to reference type; ignored

volatile PodRef r2 = pod1 ; // warning C4181: qualifier applied to reference type; ignored

}

程序输出:

class pod_yes_1 POD: yes Trivial Constructor: yes

class pod_yes_2 POD: yes Trivial Constructor: yes

class pod_yes_3 POD: yes Trivial Constructor: yes

class pod_yes_4 POD: yes Trivial Constructor: yes

class pod_no_1 POD: no Trivial Constructor: yes

class pod_no_2 POD: no Trivial Constructor: yes

class pod_no_3 POD: no Trivial Constructor: no

class pod_no_4 POD: no Trivial Constructor: yes

class pod_no_5 POD: no Trivial Constructor: no

class pod_no_6 POD: no Trivial Constructor: no

class pod_no_7 POD: no Trivial Constructor: no

class pod_no_8 POD: no Trivial Constructor: no

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics