読者です 読者をやめる 読者になる 読者になる

とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

std::is_podのバグ

Visual Studio 2012(Visual C++ 11.0)のstd::is_podはバグっている。

再現コード

以下のstatic_assertに失敗してしまう。

(1) void型をPOD型と判定してしまう。

(2) アクセス制御でprotectedあるいはprivateのデータメンバがあるクラスをPOD型ではないと判定してしまう。さらに、派生しているクラスをPOD型ではないと判定してしまう。

#include<type_traits>

struct access_control_protected{
protected:
 int i;
};

struct access_control_private1{
private:
 int i;
};

class access_control_private2{
 int i;
};

struct base{};
struct derived : base
{};

static_assert(std::is_pod<void>::value == false, "");

static_assert(std::is_pod<access_control_protected>::value, "");
static_assert(std::is_pod<access_control_private1>::value, "");
static_assert(std::is_pod<access_control_private2>::value, "");

static_assert(std::is_pod<derived>::value, "");

int main(){}

(1) std::is_podが内部で使っている組み込みの__is_podvoid型を正しく判定するが、ライブラリコードで余計なことをしているために、void型をPOD型と判定してしまっている。

(2) 組み込みの__is_podに仕様・実装の問題があるようだ。

Compiler Support for Type Traits (C++ Component Extensions)

POD型の定義の変更

(2)について。PODの定義はC++98からC++11で変更され制約が緩くされた。そのために変更前の古い規格に沿って実装している処理系では今回のようなバグが起きる。

N2342(POD's Revisited)

規格

N3337(PDF) 3.9/9

Scalar types, POD classes (Clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called POD types.

void型は、どれにも該当しないのでPOD型(POD types)ではない

なおPOD型の一つであるPODクラス型(POD class)についてはPOD class - とくにあぶなくないRiSKのブログを参照のこと。

他の処理系

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

GCC

(1) 4.3.6, 4.4.7, 4.5.4, 4.6.4, 4.7.3, 4.8.1で正しい結果。

(2) 4.3.6, 4.4.7でVisual Studio 2012同様問題がある。4.5.4, 4.6.4, 4.7.3, 4.8.1で正しい結果。

Clang

(1) 3.0, 3.1, 3.2, 3.3で正しい結果。

(2) 3.0, 3.1でVisual Studio 2012同様問題がある。3.2, 3.3で正しい結果。