Compilation issues with Dune::Hybrid::forEach and g++5
The following code compiles fine with g++-7 (Ubuntu 16.04). With g++-5 however, the commented lines lead to compiler/linker errors.
As explained in the comments, the linker errors are related to the static constexpr
members that are inlined by default in C++17.
I guess my question therefore boils down to why I need to call this->print(i)
instead of just print(i)
within the lambda passed to the Dune::Hybrid::forEach
loop while this is apparently not necessary in the testLambdaCapture()
method.
#include <config.h>
#include <iostream>
#include <dune/common/hybridutilities.hh>
#include <dune/common/typetraits.hh>
class Foo
{
static constexpr int myInt = 123;
static constexpr auto myIndexConstant = typename Dune::index_constant<1>();
public:
void testLambdaCapture()
{
std::cout << "testing call for int" << std::endl;
// ok
callLambda([&]() { std::cout << myInt << std::endl; });
callLambda([&, myInt = myInt]() { print(myInt); });
// linker error: undefined reference to Foo::myInt
callLambda([&]() { print(myInt); });
std::cout << "\ntesting call for Dune::index_constant" << std::endl;
// ok
callLambda([&, myIndexConstant = myIndexConstant]() { std::cout << myIndexConstant << std::endl; });
callLambda([&, myIndexConstant = myIndexConstant]() { print(myIndexConstant); });
// linker error: undefined reference to Foo::myIndexConstant
callLambda([&]() { std::cout << myIndexConstant << std::endl; });
callLambda([&]() { print(myIndexConstant); });
}
template<class Lambda>
void callLambda(Lambda lambda)
{
lambda();
}
template<class U>
void print(const U& u)
{
std::cout << u << std::endl;
}
void testRange()
{
std::cout << "\ntesting range" << std::endl;
using namespace Dune::Hybrid;
forEach(integralRange(2), [&, myIndexConstant = myIndexConstant](auto&& i)
{
// ok
if (i != myIndexConstant)
this->print(i);
// compiler error: cannot call member function ‘void Foo::print(U&) [with U = int]’ without object
if (i != myIndexConstant)
print(i);
});
}
};
int main()
{
Foo foo;
foo.testLambdaCapture();
foo.testRange();
return 0;
}
Edited by Kilian Weishaupt