Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmath and y0 name of variable not compiling

Tags:

c++

cmath

I got variable named y0 and included cmath, when compiling it with g++ without any args, I get a compilation error

error: invalid operands of types ‘double(double) throw ()’ and ‘double’ to binary ‘operator+’ y = y0 + R; ~~~^~~

For an experiment, I removed cmath including and everything compiles ok.

#include <iostream>
#include <cmath>

double y0, y, R;
int main() {
    std::cin >> y0 >> R; 
    y = y0 + R;
}
like image 772
Егор Лебедев Avatar asked Nov 28 '19 15:11

Егор Лебедев


1 Answers

The compiler g++ you are using is unconditionally defining the macro _GNU_SOURCE. The macro _GNU_SOURCE is working according to man feature_test_macros . The macro causes the GNU C library implementation glibc to define a lot of additional gnu extensions which pollute the global namespace. In glibc the include file cmath includes math.h.

One of those gnu extensions is for example double y0(double) function which is a gnu extension to calculate Bessel functions. If you try to declare your own y0 symbol in the global namespace as a different symbol, the compiler should complain about conflicting types declared for y0 symbol. One of the errors you are seeing is that because the symbol y0 is declared as a function, the compiler can't + add it.

The proper work-not-around would be to properly resolve the mess in glibc and help the developers all around the world - patch glibc and g++ not to export gnu extension functions while compiling in c++. As still indicated by libstdc++ faq: We'd like to find a cleaner solution, but nobody yet has contributed the time.

Another workaround would be undefine the _GNU_SOURCE symbol in g++ with -U_GNU_SOURCE compiler switch. This can cause errors about undeclared symbols in math template functions upon use, because many math functions implementation in glibc/libstdc++ use gnu extensions. Another workaround would be to use another standard C++ library implementation that doesn't suffer from this issue.

A realistic workaround would be not to declare y0 symbol in the global namespace. Just add a namespace around and reference it properly it:

namespace my {
   double y0;
}
int main() { 
   my::y0 = 1;
}
like image 97
KamilCuk Avatar answered Sep 30 '22 14:09

KamilCuk