I'm trying to compile some code utilizing C++11's library on a linux server. The code compiles fine on my mac with this line in my makefile:
CC = clang++ -std=c++11 -stdlib=libc++
However, when I try and compile the same code on a Linux server, with gcc version 4.8.1, I get the following error:
$ /usr/local/share/gcc481/bin/g++ -std=c++11 server.cpp
In file included from /auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/random:50:0,
from ellipse-graph.h:6,
from server.cpp:1:
/auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/bits/random.h: In instantiation of 'class std::uniform_int_distribution<double>':
server.cpp:17:59: required from here
/auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/bits/random.h:1668:7: error: static assertion failed: template argument not an integral type
static_assert(std::is_integral<_IntType>::value,
^
In file included from /auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/bits/move.h:57:0,
from /auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/bits/stl_pair.h:59,
from /auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/bits/stl_algobase.h:64,
from /auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/vector:60,
from interval.h:4,
from vertex.h:4,
from ellipse-graph.h:4,
from server.cpp:1:
/auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/type_traits: In instantiation of 'struct std::make_unsigned<double>':
/auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/bits/random.tcc:884:57: required from 'std::uniform_int_distribution<_IntType>::result_type std::uniform_int_distribution<_IntType>::operator()(_UniformRandomNumberGenerator&, const std::uniform_int_distribution<_IntType>::param_type&) [with _UniformRandomNumberGenerator = std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>; _IntType = double; std::uniform_int_distribution<_IntType>::result_type = double]'
/auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/bits/random.h:1770:51: required from 'std::uniform_int_distribution<_IntType>::result_type std::uniform_int_distribution<_IntType>::operator()(_UniformRandomNumberGenerator&) [with _UniformRandomNumberGenerator = std::linear_congruential_engine<long unsigned int, 16807ul, 0ul, 2147483647ul>; _IntType = double; std::uniform_int_distribution<_IntType>::result_type = double]'
server.cpp:20:40: required from here
/auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/type_traits:1531:62: error: invalid use of incomplete type 'class std::__make_unsigned_selector<double, false, false>'
{ typedef typename __make_unsigned_selector<_Tp>::__type type; };
^
/auto/pkg/gcc-4.8.1/share/gcc481/include/c++/4.8.1/type_traits:1495:11: error: declaration of 'class std::__make_unsigned_selector<double, false, false>'
class __make_unsigned_selector;
^
It appears the issue is the header. When I look here https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.200x, at "26.5", it appears that gcc 4.8.1 doesn't support random number generation, unless I'm interpreting this incorrectly. How might I compile this file?
Related
I defined a map like this :
std::map<std::string,LexType> lexname_s = { { "PROGRAM" , PROGRAM}}
And a LexType, like this :
typedef enum
{
ENDFILE, ERROR,
PROGRAM, PROCEDURE, TYPE, VAR, IF,
} LexType;
In Visual Studio Code, it always shows error type when I touch it.
//
I add more details for what i said.
the line
std::map<std::string,LexType> lexname_s = { { "PROGRAM" , PROGRAM}}
show error . it seems i can't initialize it in this way.
I compile it in the gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) in a cloud server which is centos7.
AND the error code shows below
from parse.cpp:1:
../utils.h:52:27: error: invalid conversion from ‘int’ to ‘const LexType&’ [-fpermissive]
{"ERROR", ERROR}};
^
In file included from /usr/include/c++/4.8.2/bits/stl_algobase.h:64:0,
from /usr/include/c++/4.8.2/bits/stl_tree.h:61,
from /usr/include/c++/4.8.2/map:60,
from ../globals.h:6,
from parse.h:4,
from parse.cpp:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:112:26: error: initializing argument 2 of ‘constexpr std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = const std::basic_string<char>; _T2 = LexType]’ [-fpermissive]
_GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)```
EOF(which shows in the map define) is a reserved a macro defined in stdio.h
it's the problem of it.
change the name will be ok.
My colleague ran into an unexpected issue with emplace_back and I am trying to wrap my head around it. The following test.cpp is a minimal example that reproduces the issue:
#include <vector>
class A {
public:
explicit A(int /*unused*/) {}
};
int main() {
double foo = 4.5;
std::vector<A> a_vec{};
a_vec.emplace_back(foo); // No warning with Wconversion
A a(foo); // Gives compiler warning with Wconversion as expected
}
Compiling with g++ 8.3.0 yields the following warning:
$ g++ -Wconversion test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:10:10: warning: conversion from ‘double’ to ‘int’ may change value [-Wfloat-conversion]
A a(bar); // Gives compiler warning with Wconversion as expected
So the implicit conversion is caught when a simple object is constructed, but not when emplace_back is called.
Why is there no warning for emplace_back?
This is a consequence of how the default allocator constructs an A. When you do A a{foo, bar} you are using list initialization and a narrowing conversion is required to issue a diagnostic. With the default allocator, it uses
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)
where p is a pointer to the element of the vector data and T is the value_type of the vector. Here they use parentheses instead of braces and with parentheses narrowing conversions are allowed so you don't see a diagnostic message.
If you wrote your own allocator that did
::new (static_cast<void*>(p)) T{std::forward<Args>(args)...}
Then you would get the warning.
In order to get the warning you need to compile with:
$ g++ -Wsystem-headers -Wconversion test.cpp -o test
In file included from /usr/include/c++/8/vector:60,
from test.cpp:1:
/usr/include/c++/8/bits/stl_algobase.h: In function ‘constexpr int std::__lg(int)’:
/usr/include/c++/8/bits/stl_algobase.h:1001:44: warning: conversion from ‘long unsigned int’ to ‘int’ may change value [-Wconversion]
{ return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); }
^
/usr/include/c++/8/bits/stl_algobase.h: In function ‘constexpr unsigned int std::__lg(unsigned int)’:
/usr/include/c++/8/bits/stl_algobase.h:1005:44: warning: conversion from ‘long unsigned int’ to ‘unsigned int’ may change value [-Wconversion]
{ return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); }
^
In file included from /usr/include/x86_64-linux-gnu/c++/8/bits/c++allocator.h:33,
from /usr/include/c++/8/bits/allocator.h:46,
from /usr/include/c++/8/vector:61,
from test.cpp:1:
/usr/include/c++/8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = A; _Args = {double&}; _Tp = A]’:
/usr/include/c++/8/bits/alloc_traits.h:475:4: required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = A; _Args = {double&}; _Tp = A; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<A>]’
/usr/include/c++/8/bits/vector.tcc:103:30: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {double&}; _Tp = A; _Alloc = std::allocator<A>]’
test.cpp:9:25: required from here
/usr/include/c++/8/ext/new_allocator.h:136:4: warning: conversion from ‘double’ to ‘int’ may change value [-Wfloat-conversion]
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
The warning is no longer as clear, since it happens in a system header. Note that it is not enough to only use the -Wsystem-headers flag, one needs both -Wsystem-headers and -Wconversion to catch this.
In the case of push_back it is enough to use -Wnarrowing to get a warning.
I'm trying to compile the following code:
#include <boost/optional.hpp>
void foo(boost::optional<unsigned> x = boost::none);
placed in the file a.cu, with the CUDA compiler, using the following command line:
nvcc a.cu -c --std=c++11 -I/opt/boost/include
but I get a bunch of errors:
a.cu:2:53: error: conversion from ‘const boost::none_t(boost::none_t::init_tag (*)())’ to ‘boost::optional<unsigned int>’ is ambiguous
void foo(boost::optional<unsigned> x = boost::none);
^
/opt/boost/include/boost/optional/optional.hpp:805:1: note: candidate: boost::optional<T>::optional(boost::optional<T>::rval_reference_type) [with T = unsigned int; boost::optional<T>::rval_reference_type = unsigned int&&] <near match>
optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
^ ~~~~
/opt/boost/include/boost/optional/optional.hpp:805:1: note: conversion of argument 1 would be ill-formed:
a.cu:2:53: error: invalid conversion from ‘const boost::none_t (*)(boost::none_t::init_tag (*)())’ to ‘unsigned int’ [-fpermissive]
void foo(boost::optional<unsigned> x = boost::none);
^
/opt/boost/include/boost/optional/optional.hpp:800:1: note: candidate: boost::optional<T>::optional(boost::optional<T>::argument_type) [with T = unsigned int; boost::optional<T>::argument_type = const unsigned int&] <near match>
optional ( argument_type val ) : base(val) {}
^ ~~~~
/opt/boost/include/boost/optional/optional.hpp:800:1: note: conversion of argument 1 would be ill-formed:
a.cu:2:53: error: invalid conversion from ‘const boost::none_t (*)(boost::none_t::init_tag (*)())’ to ‘unsigned int’ [-fpermissive]
void foo(boost::optional<unsigned> x = boost::none);
Why does this happen, and can I circumvent the problem while still actually using boost::optional in (host-side) code compiled with nvcc?
Additional information:
The code compiles fine with g++ 6.3.0 (my distribution's compiler).
This code (or rather, similar code) used to compile and work on an earlier Linux distribution I was using, where the compiler was g++ 5.4.x .
I've tried this with Boost versions 1.65.1 and 1.69.0 .
I've tried this with CUDA versions 9.2.88 and 10.0.130 .
I had the exact same error and was able to get this to work with this modification:
#define BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE
#include <boost/optional.hpp>
This is using CUDA 10.0.130, g++ 7.3.0, and Boost 1.68.0.
A partial answer to the second question:
You could consider using Andrzej Krzemieński's neat and self-contained implementation of an optional instead of boost::optional. It works with C++11, which is what you seem to be doing.
The following example
// file mysort.cc
#include <string>
#include <vector>
#include <algorithm>
#include <string.h>
void mysort (const char**tab, unsigned size) {
std::vector<int> vecix;
vecix.resize(size);
struct CompareIndex {
const char**t;
CompareIndex(const char**p) : t(p) {};
bool operator() (int l, int r) {
return strcmp(t[l], t[r])<0;
}
};
CompareIndex compix(tab);
for (unsigned ix=0; ix<size; ix++) vecix[ix] = ix;
std::stable_sort(vecix.begin(), vecix.end(), compix);
std::vector<const char*> vecstr;
vecstr.resize(size);
for (unsigned ix=0; ix<size; ix++) vecstr[ix] = tab[vecix[ix]];
for (unsigned ix=0; ix<size; ix++) tab[ix] = vecstr[ix];
}
fails to compile (using GCC 4.8.2 on Debian/Sid/x86-64 in C++03 standard)
mysort.cc: In function 'void mysort(const char**, unsigned int)':
mysort.cc:19:58: error: no matching function for call to
'stable_sort(std::vector<int>::iterator,
std::vector<int>::iterator,
mysort(const char**, unsigned int)::CompareIndex&)'
std::stable_sort(vecix.begin(), vecix.end(), compix);
^
In file included from /usr/include/c++/4.8/algorithm:62:0,
from mysort.cc:4:
/usr/include/c++/4.8/bits/stl_algo.h:5682:5: note:
template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)
stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
^
/usr/include/c++/4.8/bits/stl_algo.h:5682:5: note:
template argument deduction/substitution failed:
mysort.cc: In substitution of 'template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)
[with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >;
_Compare = mysort(const char**, unsigned int)::CompareIndex]':
mysort.cc:19:58: required from here
mysort.cc:19:58: error: template argument for
'template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)'
uses local type 'mysort(const char**, unsigned int)::CompareIndex'
std::stable_sort(vecix.begin(), vecix.end(), compix);
^
mysort.cc:19:58: error: trying to instantiate
'template<class _RAIter, class _Compare>
void std::stable_sort(_RAIter, _RAIter, _Compare)'
The above was compiled with GCC 4.8 using
g++ -Wall -c mysort.cc
I am getting the same error with
g++ -std=c++03 -Wall -c mysort.cc
or with
g++ -std=c++98 -Wall -c mysort.cc
but no errors with
g++ -std=c++11 -c mysort.cc
given that my g++ -v is a gcc version 4.8.2 (Debian 4.8.2-12)
but with Clang/LLVM 3.4 compiling with
clang++ -Wall -c mysort.cc
I'm getting only a warning:
mysort.cc:19:7: warning: template argument uses local
type 'CompareIndex'
[-Wlocal-type-template-args]
std::stable_sort(vecix.begin(), vecix.end(), compix);
^~~
1 warning generated.
(and I still get only a warning not an error when passing -std=c++03 or -std=c++98 to clang++ but no warnings with clang++ -std=c++11)
so my question is: why the error by GCC and the warning by Clang? Is my code legal and without undefined behavior (w.r.t. the C++03 standard)? Should I make my CompareIndex a global struct in my compilation unit?
motivations
Of course, this is a silly way to sort an array of C strings.
The real code is a bit different. In fact, I am trying to use std::stable_sort in my MELT plugin (a domain specific language to extend and customize GCC). MELT is generating C++ code and has a copying garbage collector (so pointers are moved by the GC). Hence, I need to sort using an array of indexes: the compare function in fact calls a MELT closure (which could trigger the copying GC at arbitrary moment), so I need to sort by indexes (and not by raw pointers). I want to keep the C++ code generated by MELT conforming to the C++ standard (03 or 98) required to compile GCC.
work-around
Thanks to juanchopanza's answer I've solved the issue by moving the declaration of CompareIndex at global scope before mysort.
I just committed the svn revision 206748 of the MELT branch of GCC; its file gcc/melt/warmelt-base.melt contains now a multiple_sort_new MELT function (to replace multiple_sort when it is working well) using std::stable_sort, and a global Melt_Sort_Compare_Index class in the generated C++ code.
Using local types as template arguments is not allowed in C++03.
From ISO/IEC 14882, 14.3.1 Template type arguments [temp.arg.type]:
A local type, a type with no linkage, an unnamed type or a type
compounded from any of these types shall not be used as a
template-argument for a template type-parameter.
The example given is along these lines:
template <typename T> struct Foo {};
void foo()
{
struct Bar {};
Foo<Bar> b1; // error: local type used as template-argument
Foo<Bar*> x4; // error: pointer to local type used as template-argument
}
This restriction has been lifted in C++11.
I am unable to Compile GMP on OSX 10.9. I am not entirely sure, if the problem is OSX 10.9 specific but what happens is compilation is successful but make check fails.
Please note if I don't use --enable-cxx compilation and make check both succeeds.
The full error is:
c++ -DHAVE_CONFIG_H -I. -I../.. -I../.. -I../../tests -O2 -pedantic -fomit-frame-pointer -m64 -mtune=corei7 -march=corei7 -c -o t-cast.o t-cast.cc
brew: superenv removed: -O2 -pedantic -m64 -mtune=corei7 -march=corei7
In file included from t-cast.cc:20:
In file included from ../../gmp.h:51:
/Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/cstddef:51:9: error: no member named
'ptrdiff_t' in the global namespace
using ::ptrdiff_t;
~~^
In file included from t-cast.cc:21:
In file included from ../../gmpxx.h:29:
In file included from /Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/algorithm:594:
In file included from /Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:596:
/Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/iterator:386:13: error: unknown type name
'ptrdiff_t'
typedef ptrdiff_t difference_type;
^
/Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/iterator:413:56: error: unknown type name
'ptrdiff_t'
template<class _Category, class _Tp, class _Distance = ptrdiff_t, ^/Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/iterator:720:66: error: unknown type name
'ptrdiff_t' class _Traits = char_traits<_CharT>, class _Distance = ptrdiff_t>
^
/Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/iterator:720:54: error: template parameter
missing a default argument
class _Traits = char_traits<_CharT>, class _Distance = ptrdiff_t>
^
/Applications/Xcode5-DP2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/iterator:720:27: note: previous default
template argument defined here class _Traits = char_traits<_CharT>, class _Distance = ptrdiff_t>
Remove the __need_size_t define and undef in gmp.h. It'll import ptrdiff_t too, rather than just size_t.