cmathをincludeするとy0, y1などのグローバル変数が使えなくなる問題


このエントリーをはてなブックマークに追加

一見問題なさそうな以下のコード

#include <cmath>

int x1, y1;

int main() {
    x1 = 10;
    y1 = 5;
    return 0;
}

を、例えばVisual C++ 2015でコンパイルしようとすると、以下のエラーが出て失敗します。

main.cpp(3): error C2365: 'y1': redefinition; previous definition was 'function'

原因は、cmathにて、第二種ベッセル関数を求める関数y0(), y1(), yn()が定義されていることです。実際にこのエラーにぶつかるまでまったく知りませんでした。 C++系のヘッダファイルであればすべてstd名前空間の下で関数が提供されるものかと思っていましたが、そうではないようです。

変数名を変更する、またはグローバル変数からローカル変数に変更することで上記エラーを回避できます。以下は後者の例。

#include <cmath>
int main() {
    int x1 = 10;
    int y1 = 5;

    return 0;
}

ここからは余談です。cmathで提供されるy1()関数を使う以下のコード

#include <iostream>
#include <cmath>

int main(void)
{
    std::cout << y1(10) << std::endl;
    return 0;
}

は、g++ 4.9.3では問題なくコンパイルできますが、VC++2015でコンパイルしようとすると、

error C4996: 'y1': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _y1. See online help for details.

というエラーが出てコンパイルに失敗しました。指示の通りy1を_y1にするとVC++2015でコンパイルできますが、今度はg++でコンパイルできなくなります。また一つ不幸の種が生まれたという感じです。