3

次のコードは、gcc 4.6.3 ではコンパイルに失敗しますが、clang 3.1 では問題なくコンパイルされます (クラス DummyMath の 2 つのバージョンを提供しますが、どちらも同じ問題を示します)。

#include <iostream>
using namespace std;

//* // To swap versions, comment the first slash.

// ===============================================
// V1
// ===============================================
template <typename T>
class DummyMath
{
public:
    T sum(T a1, T a2);
    T mult(T a1, int n);
};

template <typename T>
T DummyMath<T>::sum(T a1, T a2)
{
    return a1 + a2;
}

template <typename T>
T DummyMath<T>::mult(T a1, int n)
{
    auto x2 = [this](T a1) -> T
    {
        return sum(a1, a1); // <------- gcc will say that "sum" was not declared in this scope! 
    };

    T result = 0;
    n = n/2;
    for(int i = 0; i < n; ++i)
        result += x2(a1);
    return result;
}
/*/
// ===============================================
// V2
// ===============================================
template <typename T>
class DummyMath
{
public:
    T sum(T a1, T a2)
    {
        return a1 + a2;
    }

    T mult(T a1, int n)
    {
        auto x2 = [this](T a1) -> T {
            return sum(a1, a1);
        };

        T result = 0;
        n = n/2;
        for(int i = 0; i < n; ++i)
            result += x2(a1);
        return result;
    }
};
//*/

int main()
{
    DummyMath<float> math;
    cout << math.mult(2.f, 4) << endl;

    return 0;
}

エラーは次のとおりです。

main.cpp:25:20: error: ‘sum’ was not declared in this scope

クラス DummyMath の両方のバージョン (V1 と V2) は gcc では失敗し、clang では両方とも成功します。それはGCCのバグですか?

ありがとう。

4

1 に答える 1

4

これは gcc 4.7.2 の既知のバグです (この質問を参照してください)。コンパイラは、 this ポインターがキャプチャされることを認識し、生成されたクロージャーにはそのポインターが含まれていますが、そのポインターはクロージャーのコンストラクターで初期化されません。

使用return this->sum(a1, a2);して動作させることができます。LiveWorkSpaceで例を実行すると、これが gcc >= 4.7.3、および Clang 3.2 と Intel 13.0.1 (出力として 8 を出力) で修正されていることがわかります。

C++11 のサポートは非​​常に流動的であり、お気に入りのコンパイラの最新バージョンにできるだけ早くアップグレードすることをお勧めします。残念ながら、ほとんどの Linux ディストリビューションは gcc 4.7.2 のパッケージ バージョンを出荷しており、gcc 4.8.0 はまだ出荷していません。ソースからコンパイルする必要があるかもしれません。

于 2013-04-15T07:21:25.890 に答える