Reputation: 154
The following code fails to compile in gcc 4.6.3, while it compiles flawless in clang 3.1 (I provide two versions of the class DummyMath, both exhibit the same problem):
#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;
}
The error is:
main.cpp:25:20: error: ‘sum’ was not declared in this scope
Both versions (V1 and V2) of class DummyMath fail in gcc, and both succeed in clang. Is that a bug in GCC?
Thanks.
Upvotes: 3
Views: 1551
Reputation: 70526
This is known bug from gcc 4.7.2 (see this question). The compiler recognizes the this pointer is to be captured and the generated closure does contain a pointer for it, but that pointer does not get initialized in the closure's constructor.
You can use return this->sum(a1, a2);
to get it to work. Running your example on LiveWorkSpace, shows that this is fixed for gcc >= 4.7.3, as well as Clang 3.2 and Intel 13.0.1 (i.e. printing 8 as output).
C++11 support is very much in flux, and it's best to upgrade to the latest version of your favorite compiler as soon as possible. Unfortunately, most Linux distributions ship packaged versions of gcc 4.7.2, and not yet for gcc 4.8.0. You might need to compile those from source.
Upvotes: 4