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

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

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

【仕様?】constexpr で謎現象【バグ?】

次のコードを g++ 4.6.0 と 4.7.0 20110430 (experimental) でコンパイルしたらよく分からないエラーがでました。仕様として正しいのか,それともコンパイラのバグなのか,どなたか教えてほしいです。

struct s
{
 int a;
 constexpr bool operator<(s const & other)const{return a < other.a;}
};

constexpr bool f(s const * p)
{
 return *p < *p;
}

void ouch()
{
 static constexpr s array[1] = {s{0}};
 constexpr bool test = f(array);
}

void safe1()
{
 static constexpr s array[1] = {s{0}};
 constexpr bool test = f(&array[0]);
}

struct t
{
 int a;
};
constexpr bool operator<(t const & lhs, t const & rhs){return lhs.a < rhs.a;}

constexpr bool f(t const * p)
{
 return *p < *p;
}

void safe2()
{
 static constexpr t array[1] = {t{0}};
 constexpr bool test = f(array);
}

int main()
{
 ouch();
 safe1();
 safe2();
}

実行結果(コンパイルエラー):

a.cpp: In function 'void ouch()':
a.cpp:15:31:   in constexpr expansion of 'f(((const s*)(& array)))'
a.cpp:9:15:   in constexpr expansion of 'p->s::operator<((* p))'
a.cpp:15:31: error: accessing value of 'array' through a 'const s' glvalue in a constant expression
a.cpp:15:17: warning: unused variable 'test' [-Wunused-variable]
a.cpp: In function 'void safe1()':
a.cpp:21:17: warning: unused variable 'test' [-Wunused-variable]
a.cpp: In function 'void safe2()':
a.cpp:38:17: warning: unused variable 'test' [-Wunused-variable]

unused variable はどうでもいいので無視してください。問題なのは前半です。constexpr な operator< を定義して呼出そうとしているのですが,コンパイラさんはいったい何を私に訴えようとしているのでしょうか。分かりません。
仕様には詳しくありませんがバグじゃないかなと思っています。
エラーが出る ouch に対し safe1 では関数 f の呼出し方を変えているだけです。 array (の先頭要素へのポインタ)を渡すのと &array[0] を渡すのは同じはずなのに safe1 ではエラーが出ません。
また, safe2 では s の operator< をメンバからグローバルに引越しさせただけの形の t というクラスを用いて,ouch と同じことをしています。こちらもエラーが出ません。
なんか,よく分からない動作ですね。バグじゃないでしょうか?それともこれが仕様でしょうか?誰か教えてください。