cmath error on MacOS c++17: call to abs ambiguous - c++

Having this error using c++17 on Mac OS.
As far as I can tell, code is correct and should work fine (compiles without issue w/ g++ and clang++ on linux).
Also, as far as I can tell, the current default mac version of clang [10.0.1] should support c++17 (full version info printout below).
So, my question is: is this actually a bug in my code, but it works by fluke on linux? Or is it an issue with MacOS clang e.g., not full c++17 implementation?
From cppref:
Defined in header (since C++17):
int abs( int n );
Other c++17 features seem to work completely fine.
#include <cmath>
// #include <cstdlib> //works if included
int main() {
int i = 1;
// return std::abs(1); // Works fine
return std::abs(i); // Fails
}
Compile with:
clang++ -std=c++17 test.cpp
Get this error:
test.cpp:7:10: error: call to 'abs' is ambiguous
return std::abs(i);
^~~~~~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:761:1: note:
candidate function
abs(float __lcpp_x) _NOEXCEPT {return ::fabsf(__lcpp_x);}
^
(... etc.)
1 error generated.
If you #include <cstdlib>, it works without error.
using -std=gnu++17 or -std=c++1z doesn't remove the problem either.
In the actual code (which is obviously more complex than the above, and actually uses c++17 features), the error happens depending on the order of my include files.
I can't replicate that in the simple example, but I assume it boils down to calling the cstdlib version instead of the cmath version.
Currently, my 'workaround' is to just put the header includes into the order that works..but this is hardly a long-term solution.
Does anyone know the cause?
Version info (error not specific to this MacOS version, also happens on my students' laptops):
Bens-iMac:test ben$ clang++ -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

See LWG Issue 2912
This has been fixed in libc++ trunk. I don't know if Apple has shipped this fix yet. As you found, including <cstdlib> is a workaround.

Related

note: 'std::thread' is defined in header '<thread>'; did you forget to '#include <thread>'?

I try to compile a simple c++ code in c++, but keep returning errors when I try to compile it with g++ in windows.
I use
g++ -std=c++0x -pthread main.cpp
The error messages are:
std::thread' is defined in header '<thread>'; did you forget to '#include <thread>'?
Which doesn't make sense because the code is just
#include<thread>
void f(int i) {}
int main() {
std::thread t(f, 1);
t.join();
return 0;
}
I believe this code works in linux, I wonder why it can't work under windows.
To use std::thread you must be compiling your code as C++11, C++14 or C++17.
You are passing -std=c++0x to gcc. c++0x was the name used for pre-release versions of the gcc C++11 impletation and, depending on your compiler version, may be incomplete.
Change your gcc command line to -std=c++11 and things most likely work better. If not, you may need to get a newer version of the compiler.
Windows has its own threading API that is not POSIX standard. What you need to find out is (how to acquire and) how to link the threading library for your compiler. It sounds like you're using MinGW? I use MSVC and it automatically links with the Windows threading libraries. Unfortunately I don't know how to do this for MinGW, so this isn't the best answer, but here is a link that might get you started:
Does MinGW-w64 support std::thread out of the box when using the Win32 threading model?

Compiler can't find 'aligned_alloc' function

I'm trying to launch the example code from aligned alloc:
#include <cstdio>
#include <cstdlib>
int main()
{
int* p1 = static_cast<int*>(std::malloc(10*sizeof *p1));
std::printf("default-aligned address: %p\n", static_cast<void*>(p1));
std::free(p1);
int* p2 = static_cast<int*>(std::aligned_alloc(1024, 1024));
std::printf("1024-byte aligned address: %p\n", static_cast<void*>(p2));
std::free(p2);
}
My compilers give me this error:
$ g++-mp-8 main.cpp -std=c++17
main.cpp:10:38: error: no member named 'aligned_alloc' in namespace 'std'
int* p2 = static_cast<int*>(std::aligned_alloc(1024, 1024));
I am working with macOS High Sierra 10.13.6 and tried to compile this code with Macport's GCC 7.3.0, 8.2.0 and CLang (Apple LLVM version 10.0.0), they all produce the same error.
Edit: It doesn't work with either std:: present or not.
Edit2: I installed macOS Mojave and that did not fix the problem. I hoped it'll reinstall macOS's toolchain but it didn't. So I guess I cannot accept provided answers until I get a more specific one.
I am not using macOS but I have similar problems on linux using a custom g++. If you look at the cstdlib header, there is something like
#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)
using ::aligned_alloc;
#endif
So aligned_alloc is only pulled into the std namespace if C++17 is available and glibcxx supports it. You can check x86_64-linux-gnu/bits/c++config.h (or something similar on macOS) if _GLIBCXX_HAVE_ALIGNED_ALLOCis defined. If not your glibc version is too old.
For clang and the libc++ implementation aligned_alloc is available if _LIBCPP_HAS_C11_FEATURES is defined which again depends on a recent version of glibc.
As an alternative you can use boost.
As the accepted answer mentions it, using boost::align::aligned_alloc solves the problem.
To fix the error without source modification, just add the following on top of the file:
#ifdef __APPLE__
#include <boost/align/aligned_alloc.hpp>
using boost::alignment::aligned_alloc;
#endif

Clang, std::next, libstdc++ and constexpr-ness

Take the following code:
#include <array>
constexpr std::array<int, 10> a{};
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
With -std=c++17 GCC compiles it flawlessly, but Clang complains that the expression is not an integral constant expression. It looks like that the problem is about the std::next which, however, should be constexpr in C++17.
Nevertheless, std::next is in the std library, not in the compiler itself, therefore there is something weird going on. And just to make things even better, the example compiles perfectly if you pass -stdlib=libc++ to Clang.
What is going on? Who is wrong and who is right?
EDIT
The issue seems to be related to clang being toolchain-ed against GCC 7.2 inside godbolt. If you add the --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot parameter to the command line, everything works flawlessly. (Thanks to #einpoklum who reported the issue to godbolt -- I have been slower ;) )
EDIT
For everyone who consider that an old compiler should work for actual standard, sorry to say that the consideration is meaningless. I am talking about the last versions of both GCC and Clang. And the problem is reproducible with the trunk version of both. Older compilers are not relevant for this question (MSVC behaviour would be interesting, instead).
Compiling in Wandbox
#include <array>
int main()
{
constexpr std::array<int, 10> a{};
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
}
with clang++ 4.0.1 and command line
clang++ prog.cc -Wall -Wextra -std=c++1z
I get the error
prog.cc:6:18: error: static_assert expression is not an integral constant expression
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:6:18: note: non-constexpr function 'next<const int *>' cannot be used in a constant expression
/opt/wandbox/clang-4.0.1/include/c++/v1/iterator:599:1: note: declared here
next(_InputIter __x,
^
1 error generated.
But compiling with clang++ 5.0.0 (or 6.0.0 or 7.0.0 HEAD) with
clang++ prog.cc -Wall -Wextra -std=c++17
So it seems a low support for C++17 in clang++ 4.0.1 (and/or libraries used by clang++), corrected in the following versions.
-- EDIT --
The problem is confirmed (see einpoklum's answer) for clang++ 5.0.0 and clang++ 6.0.0 in gobold.
So I suppose the problem is the version of libstdc++: seems that gobold is using a version (a older one, I suppose) where std::next() isn't defined as constexpr where wandbox is using a version where std::next() is constexpr.
With the Clang 6.0.0 and 5.0.0 version on GodBolt.org, your code does indeed fail to compile. But - with clang 5.0.0-3 on my system (Lubuntu 17.10), it seems to compile without errors.
This is weird behavior. So, perhaps not the best possible answer to your question, but faced with something like this I would report it on bugs.llvm.org and see what the clang/LLVM developers say.

Clang fails to find iostream. What should I do?

Earlier, I posed a related question.
I have the following program extracted from a large project in my Mac OS
#include <iostream>
int main(){
std::cout<<"hello"<<std::endl;
return 0;
}
Compiling it with Clang fails with the following error:
$ clang test.cpp
test.cpp:1:10: fatal error: 'iostream' file not found
#include <iostream>
^
1 error generated.
For information,
A) I have already installed xcode command line tools, using xcodeselect --install. But it seems iostream does not locate in the default search path of clang.
B) Using g++ instead of clang compiles the program. But in my problem, I am not allowed to use other compiler than clang, or to change the source program.
C) I can see workaround techniques, e.g, by tweaking the search path in .bashrc or with some symbolic link, etc. But I feel reluctant to use them, because it seems that I have an installation problem with my Clang and tweaking the path only helps to avoid one of these path issues.
clang and clang++ do different things. If you want to compile C++ code, you need to use clang++
Alternatively you can invoke c++ compiler directly by providing language name explicitely:
clang -x=c++

Clang >= 3.3 in c++1y mode cannot parse <cstdio> header

I have a project that correctly compiles and runs under g++ 4.8.1 and clang >= 3.3 in c++11 mode. However, when I switch to the experimental -std=c++1y mode, clang 3.3 (but not g++) chokes on the <cstdio> header that is indirectly included by way of Boost.Test (so I cannot easily change it myself)
// /usr/include/c++/4.8/cstdio
#include <stdio.h>
// Get rid of those macros defined in <stdio.h> in lieu of real functions.
// ...
#undef gets
// ...
namespace std
{
// ...
using ::gets; // <-- error with clang++ -std=c++1y
// ...
}
with the following error message:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/cstdio:119:11:
error: no member named 'gets' in the global namespace
On this tutorial on how to set up a modern C++ environment, a similar lookup problem with max_align_t is encountered. The recommendation there is to use a sed script to surround the unknown symbols with #ifdef __clang__ macros, but that seems a fragile approach.
Setup: plain 64-bit Linux Mint 15 with
g++ (Ubuntu 4.8.1-2ubuntu1~13.04) 4.8.1
Ubuntu clang version 3.3-3~raring1 (branches/release_33) (based on
LLVM 3.3)
Questions:
what is causing this erorr? There is no __clang__ macro anywhere near the code in question, and clang in c++11 mode has no trouble at all.
Is it a language problem (does C++14 say something else than C++11 about importing C compatible symbols from the global into the std namespace)?
Do I need to change something with my include paths? (I use CMake to automatically select the header paths, and switch modes inside CMakeLists.txt)
Does clang have a switch to resolve this?
This note in the gets manpage looks relevant:
ISO C11 removes the specification of gets() from the C language, and since version 2.16, glibc header files don't expose the function declaration if the _ISOC11_SOURCE feature test macro is defined.
Probably should be
#if !_ISOC11_SOURCE
using ::gets;
#endif