次のコードは言うまでもなく違法なC++11のコードである。
#include <iostream>
enum class E : int {
arikitari = 0,
toha = 1,
nanndarouka = 2
};
static const char* strings[] = { "arikitari", "toha", "nanndarouka" };
int main(){
std::cout
<< strings[E::arikitari] << std::endl
<< strings[E::toha] << std::endl
<< strings[E::nanndarouka] << std::endl;
return 0;
}
enum classはintegral promotionしないどころかそもそも暗黙の型変換しない。
GCCのコンパイルエラー
prog.cc: In function 'int main()':
prog.cc:10:32: error: array subscript is not an integer
<< strings[E::arikitari] << std::endl
^
prog.cc:11:27: error: array subscript is not an integer
<< strings[E::toha] << std::endl
^
prog.cc:12:34: error: array subscript is not an integer
<< strings[E::nanndarouka] << std::endl;
そりゃそーだ。
Clangのコンパイルエラー
prog.cc:10:19: error: array subscript is not an integer
<< strings[E::arikitari] << std::endl
^~~~~~~~~~~~~
prog.cc:11:19: error: array subscript is not an integer
<< strings[E::toha] << std::endl
^~~~~~~~
prog.cc:12:19: error: array subscript is not an integer
<< strings[E::nanndarouka] << std::endl;
^~~~~~~~~~~~~~~
3 errors generated.
全く同じエラーだ。
VSのコンパイルエラー
source.cpp(10): error C2677: 二項演算子 '[' : 型 'E' を扱うグローバルな演算子が見つかりません (または変換できません) (新しい動作; ヘルプを参照)。
source.cpp(11): error C2677: 二項演算子 '[' : 型 'E' を扱うグローバルな演算子が見つかりません (または変換できません) (新しい動作; ヘルプを参照)。
source.cpp(12): error C2677: 二項演算子 '[' : 型 'E' を扱うグローバルな演算子が見つかりません (または変換できません) (新しい動作; ヘルプを参照)。
は?operator [
ってなんぞ!?
確かにC++の他の二項演算子はすべてオペランドの間にあるけど、operator []
だけは例外だから、解析の段階で特別扱いしてそうなものなのに、なんでこんなエラーになるのだろうか。
ちなみにVS2013 update5とVS2015 update3で全く同じエラー吐きます。
これはバグか?
で、これはバグレポを投げるべきなんだろうか?
経緯
C++「うちもそうやで」 https://t.co/bybbE6H0TY
— yumetodo-C++erだけど化学科 (@yumetodo) 2016年8月2日
@yumetodo え、enumでキャストした記憶がないのですが……
— YSR@WPF分かりません (@YSRKEN) 2016年8月2日
@YSRKEN えっ。https://t.co/gEWU6Bclph
— yumetodo-C++erだけど化学科 (@yumetodo) 2016年8月2日
@yumetodo VSだと「error C2677: 二項演算子 '[' : 型 'E' を扱うグローバルな演算子が見つかりません (または変換できません)」……
— YSR@WPF分かりません (@YSRKEN) 2016年8月2日
@yumetodo とりあえず、「E::ナントカ」という変数は、直接[]の引数などには使えないものの、「intへの暗黙の型変換」はできず(明確にstatic_castすればセーフ)、先のwandboxでもE::の手前に(int)など付けてキャストすればセーフでした
— YSR@WPF分かりません (@YSRKEN) 2016年8月2日
@yumetodo 要するに、VS的には「enum classなんだからそのまま引数なはずがない……ハッ!手前の'['がキャスト用の型では!?」といった解釈をしているのではないかと思われます
— YSR@WPF分かりません (@YSRKEN) 2016年8月2日