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.
Related
I'm using Clang 14 (on Apple M1), which has full support for C++ 17, and I'm trying to utilize the new to_chars function. Here's my very simple test file:
#include <charconv>
#include <iostream>
int main() {
char a[10];
double pi = 3.141592;
std::to_chars_result res = std::to_chars(a, a+10, pi);
*res.ptr = '\0';
std::cout << a << std::endl;
}
My compile command is clang -std=c++17 test_to_chars.cpp, and the output is below:
test_to_chars.cpp:8:30: error: call to deleted function 'to_chars'
std::to_chars_result res = std::to_chars(a, a+10, pi);
^~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/charconv:166:6: note: candidate function has been explicitly deleted
void to_chars(char*, char*, bool, int = 10) = delete;
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/charconv:450:1: note: candidate template ignored: requirement 'is_integral<double>::value' was not satisfied [with _Tp = double]
to_chars(char* __first, char* __last, _Tp __value)
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/charconv:458:1: note: candidate function template not viable: requires 4 arguments, but 3 were provided
to_chars(char* __first, char* __last, _Tp __value, int __base)
^
test_to_chars.cpp:8:24: error: no viable conversion from 'void' to 'std::to_chars_result'
std::to_chars_result res = std::to_chars(a, a+10, pi);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/charconv:154:25: note: candidate constructor (the implicit copy constructor) not viable: cannot convert argument of incomplete type 'void' to 'const std::to_chars_result &' for 1st argument
struct _LIBCPP_TYPE_VIS to_chars_result
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/charconv:154:25: note: candidate constructor (the implicit move constructor) not viable: cannot convert argument of incomplete type 'void' to 'std::to_chars_result &&' for 1st argument
2 errors generated.
I'm calling to_chars(char*, char*, double) but for some reason it's using an implicit conversion and trying to call to_chars(char*, char*, bool, int = 10) instead, which is a deleted function.
Is there a way for me to tell C++ that I don't want it to convert my double parameter to a bool?
I'm using Clang 14 (on Apple M1), which has full support for C++ 17
This is unfortunately not correct. While the compiler itself has full C++17 support, the stdlib of your clang version (Apple clang 14) does not implement any floating point charconv features.
See the entry "Elementary string conversions" in the cppreference table.
It is important to note that you are not running "clang 14", but "Apple clang 14". Your code snippet compiles just fine on normal clang 14.
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.
Consider the following code:
#include <complex>
int main()
{
unsigned u = 1u;
auto result = static_cast<std::complex<int>>(u);
return 0;
}
Compiling with
g++ -std=c++11 -Werror -Wsign-conversion -o a.out source_file.cpp
Causes compile error
source_file.cpp: In function ‘int main()’:
source_file.cpp:8:51: error: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Werror=sign-conversion]
auto result = static_cast<std::complex<int>>(u);
^
clang reports a similar error
source_file.cpp:6:50: error: implicit conversion changes signedness: 'unsigned int' to 'const value_type' (aka 'const int') [-Werror,-Wsign-conversion]
auto result = static_cast<std::complex<int>>(u);
~~~~~~~~~~~ ^
The error does not make much sense at first sight, what am I missing?
You get a conversion warning not from the cast, but from inside construction of std::complex.
To 'fix' your example you should instead do:
auto result = std::complex<int>{static_cast<int>(u)};
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?