Decimal GCC library - c++

I wrote this simple code just to check whether the #include <decimal/decimal> worked:
#include <iostream>
#include <decimal/decimal>
using namespace std;
int main ()
{
cout << "Hello, world!" << endl;
return 0;
}
I compiled it with:
$ g++ main.cpp -o exe
But I get this error message:
In file included from main.cpp:2:0:
/opt/local/include/gcc47/c++/decimal/decimal:39:2: error: #error This file requires compiler and library support for ISO/IEC TR 24733 that is currently not available.
/opt/local/include/gcc47/c++/decimal/decimal:230:56: error: unable to emulate 'SD'
/opt/local/include/gcc47/c++/decimal/decimal:251:5: error: 'std::decimal::decimal32::decimal32(std::decimal::decimal32::__decfloat32)' cannot be overloaded
... lots more similar errors ... (removed by Mats Petersson)
What does this mean? How can I fix it?

When building gcc you can enable support for C's decimal support of TR24732. The C TR creates built-in types like _Decimal64which are given nicer names by including <decimal.h>, e.g., decimal64. These built-in types are also available in C++ when gcc is configured when building to include decimal support.
The decimal support forC++ is defined by TR27433 and would be made available by including <decimal/decimal>. With gcc decimal support in C++ seems to be only available if gcc is compiled with decimal support enabled, i.e., it seems it uses the same built-in types as the C code does.
In either case it seems the decimal support in gcc doesn't cover everything specified by the respective TRs. In particular, last time I checked I/O support was missing.

Related

Using POSIX feature test macros with C++

When I'm building POSIX C programs, I want to be portable and use only POSIX or standard C library functions. So, for example, with gcc or clang, I build like this:
gcc -std=c99 -D_XOPEN_SOURCE=600
Setting the standard to C99 removes all extensions, then _XOPEN_SOURCE exposes POSIX interfaces. I no longer have the environment polluted with extensions from GNU, BSD, etc.
However, the waters seem murkier with C++. I want to do this:
g++ -std=c++14 -D_XOPEN_SOURCE=600
This has worked fine for me on various operating systems: Linux/glibc, Haiku, MinGW, macOS, at least. But apparently, there are problems with POSIX feature test macros and C++. Oracle docs have this to say:
C++ bindings are not defined for POSIX or SUSv4, so specifying feature test macros such as _POSIX_SOURCE, _POSIX_C_SOURCE, and _XOPEN_SOURCE can result in compilation errors due to conflicting requirements of standard C++ and these specifications.
While I don't have a copy of Oracle Solaris, I am seeing issues with FreeBSD and OpenBSD.
On FreeBSD:
#include <iostream>
int main() { }
$ clang++ -std=c++14 -D_POSIX_C_SOURCE=200112L t.cpp
In file included from t.cpp:1:
In file included from /usr/include/c++/v1/iostream:37:
In file included from /usr/include/c++/v1/ios:215:
/usr/include/c++/v1/__locale:631:16: error: use of undeclared identifier 'isascii'
return isascii(__c) ? (__tab_[static_cast<int>(__c)] & __m) !=0 : false;
...
(This builds fine with _XOPEN_SOURCE=600). C++ headers on FreeBSD use isacii, a non-standard function, so it's not exposed when _POSIX_C_SOURCE is set.
Or on OpenBSD:
#include <fstream>
int main() { }
$ clang++ -std=c++14 -D_XOPEN_SOURCE=600 t.cpp
In file included from t.cpp:1:
In file included from /usr/include/c++/v1/fstream:183:
In file included from /usr/include/c++/v1/ostream:138:
In file included from /usr/include/c++/v1/ios:215:
In file included from /usr/include/c++/v1/__locale:32:
In file included from /usr/include/c++/v1/support/newlib/xlocale.h:25:
/usr/include/c++/v1/support/xlocale/__strtonum_fallback.h:23:64: error: unknown type name 'locale_t'
char **endptr, locale_t) {
Presumably <locale.h> isn't getting included somewhere it “should” be.
The worrisome conclusion I'm drawing is that you can't portably have a POSIX C++ environment that is free of non-POSIX extensions. These examples work fine on OpenBSD and FreeBSD if the feature test macros are removed. That looks to be because the BSD headers expose BSD functions unless in standard C mode, but they do not care about standard C++ mode (they explicitly check whether macros corresponding to C89, C99, or C11 are set). glibc looks to be the same: it still exposes non-standard C functions in standard C++ mode, so perhaps it's only a matter of time before I run into a build error there.
So the actual question is this: can you write portable POSIX C++ code which does not expose platform-specific functionality? Or if I'm targeting POSIX with C++ should I just not set any feature test macros and hope for the best?
EDIT:
I got to thinking about the implications of this (as in, why do I care?), and the following program, I think, illustrates it. This is Linux/glibc:
#include <ctime>
int dysize;
$ g++ -c -std=c++14 t.cpp
t.cpp:2:5: error: ‘int dysize’ redeclared as different kind of entity
2 | int dysize;
| ^~~~~~
In file included from t.cpp:1:
/usr/include/time.h:262:12: note: previous declaration ‘int dysize(int)’
262 | extern int dysize (int __year) __THROW __attribute__ ((__const__));
This is the standard <ctime> header, which is does not include anything called dysize. That's an old SunOS function that glibc includes for compatibility. A C program built with -std=c99 won't expose it, but C++ always does. And there's no real way of knowing which non-reserved identifiers will be used by various implementations. If -std=c++14 caused non-standard identifiers to be hidden, that would avoid this problem, but it doesn't, and I can't see a way around that.
Which might imply that the feature test macro is a red herring: the source of the problem is that, on at least some real-world implementations, C++ compilers are exposing symbols they're not supposed to.
My suggestion is to build a toolchain, and work from that with the libraries, includes, the correct compiler (perhaps a stripped version that can only use POSIX libraries, includes, etc).
To make it portable, generally you would build the application using static linkers. Other linker options may be necessary that point specifically or include your toolchain environment paths.
And if you're using POSIX threads, you may need -pthread.
I see that you are using system-wide headers and libraries, when really, you probably want a specific to your POSIX application toolchain, to avoid contamination.

Where to find standard C++17 cmath file?

Where I can find original cmath or math.h files?
I need to use a comp_ellint_1(double) function in my program. It is declared in C++17 standard in Special functions.
But my compilers(I tried g++/clang++ etc.) say this.
I found out that in core files, where standard math.h and cmath are, there are no such functions declared in cmath. It looks like it is 99 standard...
These functions are available in gcc starting with version 7.1 and in clang starting with 3.9. You either have to upgrade your compiler, or use some other implementation (according to en.cppreference.com, you can use Boost.math
This works for me. You need g++ version 7 or higher and you must specify C++17 or higher.
#include <ctgmath>
#include <iostream>
int main(int argc, char *argv[]){
double x = 0.5;
double y = std::comp_ellint_1(x);
std::cout << "x="<<x <<" -> y(x)="<<y <<std::endl;
return 0;
}
Compiled and ran as follows
$ g++ --std=c++17 test.cpp -o test
$ ./test
x=0.5 -> y(x)=1.68575
$
Incidentally, in Ubuntu 18.04, the headers are in /usr/include/c++/n/tr1/ where n=7,8, or 9 (major versions of g++ that support special math functions, as of Dec 2019)

C++ error: invalid use of ‘::’ for `std::cout`

This is probably the weirdest thing I have seen in the last few years.
I have a project that builds perfectly well in two completely different machines (openSUSE Tumbleweed and ubuntu 14.04).
I started with a new machine using kubuntu 16.04 and this error started happening:
$ g++ -std=c++14 cout_qualif.cpp -lpng -o cout_qualif
In file included from cout_qualif.cpp:1:0:
debug_utils.h:19:19: error: invalid use of ‘::’
# define msg std::cout
Clang also points an error, but with a quite different message:
$ clang -std=c++14 cout_qualif.cpp -lpng -o cout_qualif
In file included from cout_qualif.cpp:3:
In file included from /usr/include/png++/png.hpp:34:
In file included from /usr/include/png.h:317:
/usr/include/zlib.h:94:19: error: non-friend class member 'cout' cannot have a qualified name
z_const char *msg; /* last error message, NULL if no error */
^~~
./debug_utils.h:19:19: note: expanded from macro 'msg'
# define msg std::cout
~~~~~^
1 error generated.
The simplest test code I've came across is:
#include <iostream>
#include "debug_utils.h"
#include <png++/png.hpp>
int main()
{
msg << "Start" << std::endl;
png::image< png::rgb_pixel > image("input.png");
image.write("output.png");
msg << "Finish" << std::endl;
return 0;
}
And "debug_utils.h":
#ifndef DEBUG_UTILS_H
#define DEBUG_UTILS_H
#include <iostream>
# define msg std::cout
#endif // DEBUG_UTILS_H
It turns out that "png.h" includes "zlib.h" and there is defined a struct:
typedef struct z_stream_s {
// ...
z_const char *msg; /* last error message, NULL if no error */
This msg member is what is triggering the error. If I move my #include "debug_utils.h" one line below, after #include <png++/png.hpp>, everything seems to work fine.
Now finally the question:
Why this machine cannot compile my code while two other can?
Additional info:
Kubuntu 16.04:
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
$ clang --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
openSUSE Tumbleweed:
g++ is 7.1.1
Ubuntu 14.04:
Exact version not available at hand but I believe it is 4.9.x
To recap the cause of the problem
# define msg std::cout
in debug_utils.h substitutes std::cout for any instances of msg throughout the code after debug_utils.h is included. As msg is a common short identifier, particularly for a message buffer, an unintended substitution has always been a risk lurking in the code. The solution to this is obvious: Don't do that. Use a longer, less likely to be duplicated substitution or don't do it at all and replace the macro. Without seeing your usecase I'd probably replace the macro with a function that returns the correct stream and the compiler can easily inline.
The confusion and the question stems from why an error from the macro substitution only arises from a simple piece of test code when compiled on only one of three candidate PCs.
The answer is differences in the toolchain and support libraries. For one reason or another, on only one of these PCs a third-party header that uses the msg identifier is included by a third-party header included by the test program. The other two follow different inclusion paths to build the same program and avoid tripping over the unwanted substitution.

-O1/2/3 with -std=c++1y/11/98 - If <cmath> is included i'm getting error: '_hypot' was not declared in this scope

I've just updated MinGW using mingw-get-setup and i'm unable to build anyting that contains <cmath> header if I use anything larger than -O0 with -std=c++1y. (I also tried c++11 and c++98) I'm getting errors like this one:
g++.exe -pedantic-errors -pedantic -Wextra -Wall -std=c++1y -O3 -c Z:\Projects\C++\L6\src\events.cpp -o obj\src\events.o
In file included from z:\lander\mingw\lib\gcc\mingw32\4.8.1\include\c++\cmath:44:0,
from Z:\Projects\C++\L6\src\utils.h:4,
from Z:\Projects\C++\L6\src\events.cpp:10:
z:\lander\mingw\include\math.h: In function 'float hypotf(float, float)':
z:\lander\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope
{ return (float)(_hypot (x, y)); }
Is something wrong on my side?
Or version at mingw repo is bugged? And if so, is there any quick fix for this header?
To avoid any further speculation, and downright bad suggestions such as using #if 0, let me give an authoritative answer, from the perspective of a MinGW project contributor.
Yes, the MinGW.org implementation of include/math.h does have a bug in its inline implementation of hypotf (float, float); the bug is triggered when compiling C++, with the affected header included (as it is when cmath is included), and any compiler option which causes __STRICT_ANSI__ to become defined is specified, (as is the case for those -std=c... options noted by the OP). The appropriate solution is not to occlude part of the math.h file, with #if 0 or otherwise, but to correct the broken inline implementation of hypotf (float, float); simply removing the spurious leading underscore from the inline reference to _hypot (float, float), where its return value is cast to the float return type should suffice.
Alternatively, substituting an equivalent -std=gnu... for -std=c... in the compiler options should circumvent the bug, and may offer a suitable workaround.
FWIW, I'm not entirely happy with MinGW.org's current implementation of hypotl (long double, long double) either; correcting both issues is on my punch list for the next release of the MinGW runtime, but ATM, I have little time to devote to preparing this.
Update
This bug is no longer present in the current release of the MinGW.org runtime library (currently mingwrt-3.22.4, but fixed since release 3.22). If you are using anything older than this, (including any of the critically broken 4.x releases), you should upgrade.
As noted by Keith, this is a bug in the MinGW.org header.
As an alternative to editing the MinGW.org header, you can use MinGW-w64, which provides everything MinGW.org provides, and a whole lot more.
For a list of differences between the runtimes, see this wiki page.
MinGW uses gcc and the Microsoft runtime library. Microsoft's implementation support C90, but its support for later versions of the C standard (C99 and C11) is very poor.
The hypot function (along with hypotf and hypotl) was added in C99.
If you're getting this error with a program that calls hypot, such as:
#include <cmath>
int main() {
std::cout << std::hypot(3.0, 4.0)) << '\n';
}
then it's just a limitation of the Microsoft runtime library, and therefore of MinGW. If it occurs with any program that has #include <cmath>, then it's a bug, perhaps a configuration error, in MinGW.

GCC C++11 Fails to See #if windows And #if linux (Re-ask)

When using the #if windows/#if linux compilers features in Debian GCC version 4.7.2, I have been unable to get them work when using std11.
Independently, I can get the compiler to accept the if-defines without complaint. I can also get the compiler to use the same code with c++ 11, without any if-defines (and thus not conditionally). But when I run the conditional defines through the same compiler, with the tag for c++ 11, the code is rejected.
Below I have included a simple example, with two alternate mains, and the error I get. The only difference between the two mains are the commented out lines.
Runs:
g++ main.cpp -std=c++11 -o test
The above uses the c++ 11 standard. When running commented main it works perfectly. But when running uncommented main, it fails entirely, giving the error at the far end of this post.
g++ main.cpp -o test
The above does not use the c++ 11 standard. When running either commented main or uncommented main it works perfectly.
Below are the code examples.
Commented main.cpp:
#include <iostream>
//#if windows
//#include "WindowsSolution.hpp"
//#endif
//#if linux
#include "LinuxSolution.hpp"
//#endif
int main()
{
std::cout << myGlobalSolution.out() << std::endl;
return 0;
}
LinuxSolution.hpp:
class LinSolution{
public:
LinSolution(){
}
std::string out(){
std::string ret("Linux solution");
return ret;
}
};
LinSolution myGlobalSolution;
WindowsSolution.hpp:
class WinSolution{
private:
WinSolution(){
}
std::string out(){
std::string ret("Windows solution");
return ret;
}
};
WinSolution myGlobalSolution;
Uncommented main.cpp:
#include <iostream>
#if windows
#include "WindowsSolution.hpp"
#endif
#if linux
#include "LinuxSolution.hpp"
#endif
int main()
{
std::cout << myGlobalSolution.out() << std::endl;
return 0;
}
Below is the error I get when compiling with the uncommented main.cpp, using the c++ 11 flag.
main.cpp: In function ‘int main()’:
main.cpp:13:15: error: ‘myGlobalSolution’ was not declared in this scope
The simple constant linux is a GCC extension and not an official OS constant. The proper constant for Debian is probably __gnu_linux__; you can find a list of them for various systems here. Usually official predefined constants follow the convention of using __ at the start.
Your code works without the standard flag because by default GCC compiles in a GNU language mode (GNU C++) rather than a standard language mode (ISO C++); the GNU language includes extensions (extra language features, and in this case, legacy OS constants). When you pass the -std=c++11 flag you are requesting ISO language mode, which means GNU extensions are disabled, including GNU-only constants. To get both GNU extensions and a specific set of ISO features, try requesting a GNU language standard version instead (e.g. -std=gnu++11 works fine).