This fails to compile under GCC 4.6:
#if __cplusplus >= 201103L
#include <ratio>
#endif
__cplusplus should be set to "1" in GCC 4.6 according to this bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1773
How should I test for C++11 support in GCC 4.6?
EDIT: I want to use Boost ratio when built with GCC 4.6 and std ratio with GCC 4.8 and -std=c++11. The rest of the code is ready for this, it's just this include that fails to compile.
Since even compilers which theoretically support this or that standard version can have bugs, it's better to rely on specific versions which are known to produce valid results.
In G++, you can do:
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 9
// use C++11 features
#else if __GNUC__ == 5
// use C++11 features
#else
// maybe don't use some features
#endif
Just try to compile this program:
int main()
{
auto i = 0;
return 1;
}
using the command g++ -std=c++11 -c filename.cpp in your command line. auto is c++11 feature, so if that compiles with no errors, it means your compiler has support for C++11.
But in general, for gcc, before version 5.1, support for C++11 was experimental. So not until version 5.1 that gcc supported everything C++11 has to offer.
Related
with _GLIBCXX_USE_CXX11_ABI=0
std::function of GCC-4 is different of GCC-5 and follwing versions.
The following code show you the fact:
==> lib.cc <==
#include <functional>
std::function<int(const void*p)> holder;
int run_holder(const void *p)
{
return holder(p);
}
==> main.cc <==
#include <stdio.h>
#include <functional>
extern int run_holder(const void*p);
extern std::function<int(const void*p)> holder;
int foo(const void* p)
{
printf("p=%p\n", p);
return 0;
}
int main()
{
holder = foo;
foo((void*)0x12345678);
holder((void*)0x12345678);
run_holder((void*)0x12345678);
}
==> make.sh <==
#!/bin/bash
GCC4=/usr/bin/g++
GCCN="scl enable devtoolset-5 -- g++"
$GCC4 -std=c++11 -c -g lib.cc -shared -o libfoo.so &&
$GCCN -std=c++11 -L. -lfoo -g main.cc -o a.out &&
LD_LIBRARY_PATH=. ./a.out
expected result, something like:
p=0x12345678
p=0x12345678
p=0x12345678
actual result:
p=0x12345678
./make.sh: line 6: 973 Segmentation fault LD_LIBRARY_PATH=. ./a.out
The reason is the implementation of std::function changes without document.
gcc4: /usr/include/c++/4.8.2/functional:2430
typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);
gcc5: /opt/rh/devtoolset-4/root/usr/include/c++/5.3.1/functional:2226
gcc8: /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/std_function.h:609
using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
So I can not write a .so using std::function compiled by gcc4 and used by gcc5/6/7/8. There is no macro like _GLIBCXX_USE_CXX11_ABI can control the behavior.
So I can not write a .so using std::function compiled by gcc4 and used by gcc5/6/7/8.
Correct. Neither Red Hat nor the GCC project has ever claimed that's possible, quite the opposite. C++11 support in GCC 4.x was incomplete and unstable, and subject to ABI changes and API changes. What you're trying to do was never supported.
I've explained this in more detail at https://stackoverflow.com/a/49119902/981959
The Developer Toolset documentation covers it too (emphasis mine):
"A compiler in C++11 or C++14 mode is only guaranteed to be compatible with another compiler in C++11 or C++14 mode if they are from the same release series (for example from Red Hat Developer Toolset 6.x).
...
"Using the C++14 language version is supported in Red Hat Developer Toolset when all C++ objects compiled with the respective flag have been built using Red Hat Developer Toolset 6 or later. Objects compiled by the system GCC in its default mode of C++98 are also compatible, but objects compiled with the system GCC in C++11 or C++14 mode are not compatible."
There is no macro like _GLIBCXX_USE_CXX11_ABI can control the behavior.
We do not provide macros to control things that are unsupported and cannot work.
If you want to use C++11 with a mix of GCC versions you need to use a release that has stable, non-experimental support for C++11. So not GCC 4.x.
I'm catching a compile error when attempting to use unique_ptr on Apple platforms with -std=c++11:
$ make
c++ -std=c++11 -DNDEBUG -g2 -O3 -fPIC -march=native -Wall -Wextra -pipe -c 3way.cpp
In file included ...
./smartptr.h:23:27: error: no type named 'unique_ptr' in namespace 'std'
using auto_ptr = std::unique_ptr<T>;
~~~~~^
./smartptr.h:23:37: error: expected ';' after alias declaration
using auto_ptr = std::unique_ptr<T>;
According to Marshall Clow, who I consider an expert on the C++ Standard Library with Clang and Apple:
Technical Report #1 (TR1) was a set of library additions to the C++03
standard. Representing the fact that they were not part of the
"official" standard, they were placed in the namespace std::tr1.
In c++11, they are officially part of the standard, and live in the
namespace std, just like vector and string. The include files no
longer live in the "tr1" folder, either.
Take aways:
Apple and C++03 = use TR1 namespace
Apple and C++11 = use STD namespace
Use LIBCPP_VERSION to detect libc++
Now, here's what I have in smartptr.h:
#include <memory>
// Manage auto_ptr warnings and deprecation in C++11
// Microsoft added template aliases to VS2015
#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
template<typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif // C++11
I think the last thing to check is the __APPLE__ define, and here it is:
$ c++ -x c++ -dM -E - < /dev/null | grep -i apple
#define __APPLE_CC__ 6000
#define __APPLE__ 1
#define __VERSION__ "4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)"
#define __apple_build_version__ 5030040
Why am I receiving a error: no type named 'unique_ptr' in namespace 'std' when using -std=c++11?
I think these are the four test cases. It attempts to exercise the four configurations from the cross product of: {C++03,C++11} x {libc++,libstdc++}.
c++ -c test-clapple.cxx
OK
c++ -stdlib=libc++ -c test-clapple.cxx
OK
c++ -std=c++11 -c test-clapple.cxx
FAIL
c++ -std=c++11 -stdlib=libc++ -c test-clapple.cxx
OK
Here is the test driver. Be sure to test it on OS X so you get the full effects of the TR1 namespace in 2015.
$ cat test-clapple.cxx
// c++ -c test-clapple.cxx
// c++ -stdlib=libc++ -c test-clapple.cxx
// c++ -std=c++11 -c test-clapple.cxx
// c++ -std=c++11 -stdlib=libc++ -c test-clapple.cxx
#include <memory>
// Manage auto_ptr warnings and deprecation in C++11
#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
template<typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif // C++11
int main(int argc, char* argv[])
{
return argc;
}
And the CFE Devs specifically told me to use that code;
No they didn't. They told you to do something similar if you want to use shared_ptr, because for C++03 <tr1/memory> defines std::tr1::shared_ptr and for C++11 <memory> defines std::shared_ptr.
But you're not using shared_ptr. If you want to use auto_ptr then it's just std::auto_ptr, everywhere, which is always defined in <memory>.
I think you've misunderstood Marshall's comment and you're overcomplicating things. What you quoted ('In c++11, they are officially part of the standard, and live in the namespace std, just like vector and string. The include files no longer live in the "tr1" folder, either.') is not Apple-specific or Clang-specific, it applies to all compilers. But since auto_ptr was never part of TR1 and never in <tr1/memory> it's irrelevant that the contents of TR1 are now in namespace std, because what you're trying to use was never included in TR1.
You should not be using TR1 at all here.
# include <memory>
// Manage auto_ptr warnings and deprecation in C++11
#if (__cplusplus >= 201103L)
template<typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif // C++11
This should be correct for modern compilers, but won't work on the stupid configuration that comes with XCode, which is a modern version of Clang that supports C++11 and the libstdc++ from GCC 4.2 which is nearly ten years old and doesn't support unique_ptr.
To cope with the default OS X toolchain this works:
#include <memory>
#if __cplusplus >= 201103L
# ifdef __clang__
# if __has_include(<forward_list>)
// either using libc++ or a libstdc++ that's new enough to have unique_ptr
# define HAVE_UNIQUE_PTR 1
# endif
# else // not clang, assume unique_ptr available
# define HAVE_UNIQUE_PTR 1
# endif
#endif
#ifdef HAVE_UNIQUE_PTR
template<typename T> using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif
This works by using the presence of <forward_list> as an indicator of whether the standard library clang is using supports std::unique_ptr.
If clang is using libc++ as its standard library then all versions support unique_ptr and also provide <forward_list>, so the test passes.
If clang is using libstdc++ then whether unique_ptr is supported depends on the libstdc++ version. unique_ptr was added to libstdc++ in GCC 4.3, which is the same version that added <forward_list>, so if that header is available then unique_ptr will be too. If you are using clang with the ancient libstdc++ that ships with the Apple toolchains (from GCC 4.2) then unique_ptr is not supported, but neither is <forward_list>, so the test fails and you use auto_ptr instead.
That should work for any GCC/libstdc++, Clang/libc++ or Clang/libstdc++ combination found in the wild. I don't know what is needed for VC++/Dinkumware and Clang/Dinkumware, from your answer it looks like maybe you would just change the first condition to:
#if __cplusplus >= 201103L || _MSC_VER >= 1600
After I declared a variable in this way:
#include <thread>
namespace thread_space
{
thread_local int s;
} //etc.
i tried to compile my code using 'g++ -std=c++0x -pthread [sourcefile]'. I get the following error:
example.C:6:8: error: thread-local storage is unsupported for the current target
static thread_local int s;
^
1 error generated.
If i try to compile the same code on Linux with GCC 4.8.1 whit the same flags, i get a functioning executable file. I'm using clang-503.0.40 (the one which comes with Xcode 5.1.1) on a MacBook Pro running OSX 10.9.3. Can anybody explain me what i'm doing wrong?
Thank you!!
Try clang++ -stdlib=libc++ -std=c++11. OS X's outdated libstdc++ doesn't support TLS.
Edit
Ok, this works for the normal clang version but not for the Xcode one.
I did a diff against Apple's clang (503.0.38) and the normal released one and found the following difference:
.Case("cxx_thread_local",
- LangOpts.CPlusPlus11 && PP.getTargetInfo().isTLSSupported() &&
- !PP.getTargetInfo().getTriple().isOSDarwin())
+ LangOpts.CPlusPlus11 && PP.getTargetInfo().isTLSSupported())
So I think this is a bug in Apple's clang version (or they kept it in there on purpose - but still weird, because -v says based on 3.4).
Alternatively, you can use compiler extensions such as __thread (GCC/Clang) or __declspec(thread) (Visual Studio).
Wrap it in a macro and you can easily port your code across different compilers and language versions:
#if HAS_CXX11_THREAD_LOCAL
#define ATTRIBUTE_TLS thread_local
#elif defined (__GNUC__)
#define ATTRIBUTE_TLS __thread
#elif defined (_MSC_VER)
#define ATTRIBUTE_TLS __declspec(thread)
#else // !C++11 && !__GNUC__ && !_MSC_VER
#error "Define a thread local storage qualifier for your compiler/platform!"
#endif
...
ATTRIBUTE_TLS static unsigned int tls_int;
The clang compiler included in the Xcode 8 Beta and GM releases supports the C++11 thread_local keyword with both -std=c++11 and -std=c++14 (as well as the GCC variants).
Earlier versions of Xcode apparently supported C-style thread local storage using the keywords __thread or _Thread_local, according to the WWDC 2016 video "What's New in LLVM" (see the discussion beginning at 5:50).
Seems like you might need to set the minimum OS X version you target to 10.7 or higher.
When I compile the following code containing the design C++11, in Windows7x64 (MSVS2012 + Nsight 2.0 + CUDA5.5), then I do not get errors, and everything compiles and works well:
#include <thrust/device_vector.h>
int main() {
thrust::device_vector<int> dv(10);
auto iter = dv.begin();
return 0;
}
But when I try to compile it under the Linux64 (Debian 7 Wheezey + Nsight Eclipse from CUDA5.5), I get errors:
../src/CudaCpp11.cu(5): error: explicit type is missing ("int"
assumed)
../src/CudaCpp11.cu(5): error: no suitable conversion function from
"thrust::detail::normal_iterator>" to "int"
exists
2 errors detected in the compilation of
"/tmp/tmpxft_00001520_00000000-6_CudaCpp11.cpp1.ii". make: *
[src/CudaCpp11.o] Error 2
When I added line:-stdc++11
in Properties-> Build-> Settings-> Tool Settings-> Build Stages-> Preprocessor options (-Xcompiler)
I get more errors:
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h(432): error:
identifier "nullptr" is undefined
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h(432): error:
expected a ";"
...
/usr/include/c++/4.8/bits/cpp_type_traits.h(314): error: namespace
"std::__gnu_cxx" has no member
"__normal_iterator"
/usr/include/c++/4.8/bits/cpp_type_traits.h(314): error: expected a
">"
nvcc error : 'cudafe' died due to signal 11 (Invalid memory
reference) make: * [src/CudaCpp11.o] Error 11
Only when I use thrust::device_vector<int>::iterator iter = dv.begin(); in Linux-GCC then I do not get an error. But in Windows MSVS2012 all c++11 features works fine!
Can I use C++11 in the .cu-files (CUDA5.5) in Windows7x64 (MSVC) and Linux64 (GCC4.8.2)?
You will probably have to split the main.cpp from your others.cu like this:
others.hpp:
void others();
others.cu:
#include "others.hpp"
#include <boost/typeof/std/utility.hpp>
#include <thrust/device_vector.h>
void others() {
thrust::device_vector<int> dv(10);
BOOST_AUTO(iter, dv.begin()); // regular C++
}
main.cpp:
#include "others.hpp"
int main() {
others();
return 0;
}
This particular answer shows that compiling with an officially supported gcc version (as Robert Crovella stated correctly) should work out at least for c++11 code in the main.cpp file:
g++ -std=c++0x -c main.cpp
nvcc -arch=sm_20 -c others.cu
nvcc -lcudart -o test main.o others.o
(tested on Debian 8 with nvcc 5.5 and gcc 4.7.3).
To answer your underlying question: I am not aware that one can use C++11 in .cu files with CUDA 5.5 in Linux (and I was not aware the shown example with host-side C++11 gets properly de-cluttered under MSVC). I even filed a feature request for constexpr support which is still open.
The CUDA programming guide for CUDA 5.5 states:
For the host code, nvcc supports whatever part of the C++ ISO/IEC
14882:2003 specification the host c++ compiler supports.
For the device code, nvcc supports the features illustrated in Code
Samples with some restrictions described in Restrictions; it does not
support run time type information (RTTI), exception handling, and the
C++ Standard Library.
Anyway, it is possible to use some of the C++11 features like auto in kernels, e.g. with boost::auto.
As an outlook, other C++11 features like threads may be quite unlikely to end up in CUDA and I heard no official plans about them yet (as of supercomputing 2013).
Shameless plug: If you are interested in more of these tweeks, feel free to have a look in our library libPMacc which provides multi-GPU grid and particle abstractions for simulations. We implemented lambda, a STL-like access concept for 1-3D matrices and other useful stuff there.
All the best,
Axel
Update: Since CUDA 7.0 C++11 support in kernels has been added officially. As BenC pointed our correctly, parts of this feature were already silently added in CUDA 6.5.
According to Jared Hoberock (Thrust developer), it seems that C++11 support has been added to CUDA 6.5 (although it is still experimental and undocumented). This may make things easier when starting to use C++11 in very large C++/CUDA projects, since splitting everything can be quite cumbersome for large projects when you use CMake for instance.
I have a mixture of c and c++ files compiling under g++. As explained in:
What is the difference between g++ and gcc?
The c files are being compiled as c++ with the g++ command line. Not huge problem but migrating over to gcc will allow th c files to compile as c files and the c++ file to compile as c++.
What -I includes or -L libraries do I need to add to the gcc command line, that the g++ command line is including by default?
You shouldn't need to add any includes or libraries beyond what you already have.
Whatch out for C functions being called from C++ code - you need to tell the C++ compiler those are C functions so the program is linked correctly and works.
The standard practice is to add the following directives to all your C headers being included in C++ files:
#ifdef __cplusplus
extern "C" {
#endif
... C header contents go here ...
#ifdef __cplusplus
}
#endif
More info here: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
You shouldn't need to add any. If it's using C++ it should automatically bring in C++ libraries.
If not, you'll want -lstdc++ (and if you're still getting undefined references, -lc for the libc). Don't forget -lm if you use math functions.
GCC can determine which language a file is in based on the file extension. However, GCC does not automatically link in run time support for any language other than C. In practice that means you can compile C++ programs using gcc instead of g++ but you'll need to add the -lstdc++ directive:
#include <iostream>
int main()
{
std::cout << "Hello world\n";
}
g++ hello.cc
gcc hello.cc -lstdc++
More accurately, you will need to specify -lstdc++ if you you use the standard library, exceptions, operator new, or RTTI. For instance, try compiling the following without -lstdc++:
int main()
{
try {
throw 1;
}
catch (int i)
{
return i;
}
}
Please note that STL containers (including std::strings) use operator new by default. Strictly speaking you should be able to use the algorithms (std::min, std::find_first_of, etc.) binders and a few other things in the standard library without -lstdc++ but for the most part you might as well include it (the linker will ignore any libraries that you don't actually link to).
Why not compile the c objects with gcc and the c++ with g++ and then when you link, link using the g++?