Trying to use ios format flags to format the string representation of Boost multiprecision cpp_int.
Everything works with gcc standard c++17, but in Visual Studio 2019 (v142) same standard, I'm getting a compilation error when using '|' operator to combine flags:
string format_cpp_int(boost::multiprecision::cpp_int& n, bool show_base, bool uppercase)
{
auto f = std::ios::hex;
if (show_base) f = f | std::ios::showbase;
if (uppercase) f = f | std::ios::uppercase;
return n.str(0, f);
}
Getting the following error:
Severity Code Description Project File Line Suppression State
Error C2440 '=': cannot convert from 'int' to 'std::_Iosb::_Fmtflags' (compiling source file main.cpp)
Is there some difference between c++17 support in gcc and VS that i'm not aware of?
Also trying to cast the result back to fmtflags doesn't seem to work either.
f = static_cast<std::ios::fmtflags>(f | std::ios::showbase);
is there another way to combine the flags and pass to cpp_int?
Because the keyword auto may get the underlying type, which may be implemented by the specific compiler.
You should write the type immediately:
std::ios::fmtflags f = std::ios::hex;
if (show_base) f = f | std::ios::showbase;
if (uppercase) f = f | std::ios::uppercase;
Related
This c++ code compiles fine with gcc, icc, and clang, but fails with MSVC:
#include <ios>
int main()
{
auto open_flags = std::ios::binary;
open_flags |= std::ios::app;
return 0;
}
(6): error C2678: binary '|=': no operator found which takes a left-hand operand of type 'std::_Iosb::_Openmode' (or there is no acceptable conversion)
https://godbolt.org/z/999fffPEx
Changing the code to this gives a more helpful error message:
#include <ios>
int main()
{
auto open_flags = std::ios::binary;
open_flags = open_flags | std::ios::app;
return 0;
}
(6): error C2440: '=': cannot convert from 'int' to 'std::_Iosb::_Openmode'
And this compiles fine:
#include <ios>
int main()
{
auto open_flags = std::ios::binary | std::ios::out;
open_flags = open_flags | std::ios::app;
return 0;
}
This looks like incorrect behaviour to me. Like MSVC has implemented the | operator with return type int instead of ios::openmode.
It's also worth noting that the original code compiles if I use std::ios::openmode instead of auto, presumably through implicit conversion.
Is this an MSVC bug, or am I missing something? Standards references welcome!
It's a MSVC bug.
According to the standard:
binary has type std::ios_base::openmode ([ios.base.general]);
std::ios_base::openmode is a bitmask type ([ios.openmode]).
But on MSVC:
binary has an enum type (the internal type _Openmode), but std::ios_base::openmode is int.
_Openmode is not a bitmask type (and thus only built-in operators |, &, ^, ~ are applicable).
Please file a bug report (or two) at https://github.com/microsoft/STL.
I'm facing NA/NaN errors with my TMB code. Searching on the internet, I found that including fenv.h file into my code can give me a clue about the source of errors.
Since this example nan error does not work on Windows, I decided to follow an advice to run this example in Virtual TMB (Because my old desktop cannot afford to run more than one operating system).
But the new problem appeared. I get unused variable errors after running the code.
This code is copied and pasted from the link above.
cpp code
// Illustrates how to make the debugger catch a floating point error.
#include <TMB.hpp>
#include <fenv.h> // Extra line needed
template<class Type>
Type objective_function<Type>::operator() ()
{
feenableexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO | FE_UNDERFLOW); // Extra line needed
DATA_SCALAR(lambda);
PARAMETER(x);
Type f;
f = sqrt(-1.); // FE_INVALID ( sqrt(-1.) returns NaN )
//f = 1./0.; // FE_DIVBYZERO ( division by zero )
//f = exp(100000.); // FE_OVERFLOW ( exp(100000.) returns Inf ) [Does not work on all platforms]
//f = exp(-100000.); // FE_UNDERFLOW ( exp(-100000.) returns 0 )
return f;
}
and here is the corresponding r code for Linux
data <- list(lambda = 25)
parameters <- list(x=1)
require(TMB)
compile('nan.cpp','-fno-gnu-unique -O0 -Wall')
dyn.load(dynlib('nan'))
model <- MakeADFun(data, parameters)
fit <- nlminb(model$par, model$fn, model$gr)
rep <- sdreport(model)
print(rep)
I attached my sessionInfo and the warning messages via image files.
Error
nan.cpp: In instantiation of 'Type objective_function<Type>::operator()() [with Type =double]':
/home/tmb/r/library/TMB/include/tmb_core.hpp:1416:16: required from here
nan.cpp:7:15:warning:unused variable 'lambda' [-Wunused -variable]
DATA_SCALAR(lambda);
^
/home/tmb/r/library/TMB/include/tmb_core.hpp:199:32: note: in definition of macro 'DATA_SCALAR'
#define DATA_SCALAR(name) Type name(asVector<Type>( \
nan.cpp:8:13: warning: unused variable 'x' [-Wunused-variable]
PARAMETER(x);
^
/home/tmb/r/library/TMB/include/tmb_core.hpp:182:30: note: in definition of macro 'PARAMETER'
How can I solve this problem?
Thanks!
Warning message:
Session Info:
Why the g++ compiler says: error: expected unqualified-id before 'xor' token
class BigInteger{
public:
unsigned *array;
BigInteger xor(BigInteger bi){ // g++ indicates error this line
BigInteger n;
if(bi.array == (unsigned*)0){
return n;
}
return n;
}
};
xor is an alternative token for ^ in C++, you can't use it as an identifier. Same for or/bitor and and/bitand (||, |, && and & respectively), and a few others. They are essentially keywords like if or for.
Choose a different name for your function.
Full list of alternative tokens (C++ standard §2.12 Keywords, see §2.6 Alternative tokens for the mappings):
and
and_eq
bitand
bitor
compl
not
not_eq
or
or_eq
xor
xor_eq
Groan. Yes, this very thing is one of those chase-your-tail and then realize "What?" and shake your head situations.
In my case similar, I have a class definition, which defines a class method:
List* xor(List* list)
And one gets the g++ useful error message of:
error: expected unqualified-id before ‘^’ token
Eventually one finds that xor is a synonym for ^ and as such cannot be a function name.
What makes it worse (in my case) is that this works perfectly FINE in MS Windows under Visual Studio (2010 in my case). And is code that has been under development through various Visual Studio versions since 1999 (Visual Studio 6).
So now I need to rename the function and rebuild on Windows as well as g++ on linux... one of those problems that gets bigger as you work on it.
I am using Visual C++ express 2008 try to compile code similar to below:
no problem
{
...
AVRational test = {1, 1000};
...
}
but has problem when it is as below:
{
...
AVRational test = (AVRational){1, 1000};
...
}
gave errors:
1>..\..\..\projects\test\xyz.cpp(1139) : error C2059: syntax error : '{'
1>..\..\..\projects\test\xyz.cpp(1139) : error C2143: syntax error : missing ';' before '{'
1>..\..\..\projects\test\xyz.cpp(1139) : error C2143: syntax error : missing ';' before '}'
where AVRational (ffmpeg.org library) is defined as:
typedef struct AVRational{
int num; ///< numerator
int den; ///< denominator
} AVRational;
FFmpeg come with some pre-define value such as
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
which is used as below
av_rescale_q(seek_target, AV_TIME_BASE_Q, pFormatCtx->streams[stream_index]->time_base);
will failed to compile on Visual C++ express 2008
It seem like the same code will be compiled with no error/warning on gcc compiler. Why I get this error on VC++? Is it a C/C++ standard way to do casting on struct value? Anyway I can avoid this error while still able to use the defined AV_TIME_BASE_Q?
Use av_get_time_base_q() instead of AV_TIME_BASE_Q for C++ or VS.
This was fixed in a patch
VC++ 2013 does not allow compound literals in C++ but it allows them in C. Options:
Rename your program with a .c suffix
Switch on the /TC flag for the program that does not compile.
The other alternative if you wish to keep to C++ is to change the declaration of AV_TIME_BASE_Q in the header file
static const AVRational AV_TIME_BASE_Q = {1, AV_TIME_BASE};
Then it will be using the constant instead of the compound literal.
For compound-literals errors in C++
wrong:
this->buffer.enqueue((tone_t) { duration, frequency });
correct:
tone_t tone = { duration, frequency };
this->buffer.enqueue(tone);
I have the following (very simple) Ragel file scanner.rl:
void lex(string data) {
int cs, act, top;
auto p = data.ptr;
typeof(p)
pe = &data[$ -1],
eof = pe,
ts,
te;
%%{
machine scanner;
identifier = alpha . alnum**;
main := |*
identifier => { ("Identifier: " + data[ts..te]).writeln; };
space;
*|;
write data;
write init;
write exec;
}%%
}
void main() {
"this is a test".lex;
}
I convert scanner.rl to scanner.d using ragel -D scanner.rl. When I try to compile the resulting D file with dmd scanner.d, I get the following error messages:
scanner.d(97): Error: cannot implicitly convert expression
(&_scanner_actions[cast(ulong)_scanner_from_state_actions[cast(ulong)cs]])
of type const(byte)* to byte* scanner.d(110): Error: cannot implicitly
convert expression
(&_scanner_trans_keys[cast(ulong)_scanner_key_offsets[cast(ulong)cs]])
of type const(char)* to char* scanner.d(166): Error: cannot implicitly
convert expression
(&_scanner_actions[cast(ulong)_scanner_trans_actions[cast(ulong)_trans]])
of type const(byte)* to byte* scanner.rl(22): Error: cannot implicitly
convert expression (ts) of type immutable(char)* to ulong
scanner.d(186): Error: cannot implicitly convert expression
(&_scanner_actions[cast(ulong)_scanner_to_state_actions[cast(ulong)cs]]) of type const(byte)* to byte*
Perhaps I'm missing something important?
Are you sure ragel is generating D2 code? Looks like it is missing const.... looking at ragel's source code, looks like ragel -D generates D1 and ragel -E generates D2, though this isn't documented in --help!