C++ initialization of vector of structs - c++

I am trying to make a keyword-recognizing subroutine under OSX Yosemite, see the listing below. I do have a couple of strange things.
I am using the "playground" for making MWE, and the project builds seemingly OK, but does not want to run:
"My Mac runs OS X 10.10.5, which is lower than String sort's minimum deployment target."
I do not understand even the message, and especially not what my code makes with sorting?
Then, I pasted the relevant code to my app, where the project was generated using CMake, and the same compiler, and the same IDE, in the same configuration presents with the message
"Non-aggregate type 'vector cannot be initialized with an initializer list"
in the "vector QInstructions={..}" construction.
When searching for similar error messages, I found several similar questions, and the suggested solutions use default constructor, manual initialization, and the like. I wonder if standard-resistant compact initialization is possible?
#include <iostream>
using namespace std;
#include <vector>
enum KeyCode {QNONE=-1,
QKey1=100, QKey2
};
struct QKeys
{ /** The code command code*/
std::string Instr; ///< The command string
unsigned int Length; ///< The significant length
KeyCode Code; //
};
vector<QKeys> QInstructions={
{"QKey1",6,QKey1},
{"QKey2",5,QKey2}
};
KeyCode FindCode(string Key)
{
unsigned index = (unsigned int)-1;
for(unsigned int i=0; i<QInstructions.size(); i++)
if(strncmp(Key.c_str(),QInstructions[i].Instr.c_str(),QInstructions[i].Length)==0)
{
index = i;
cout << QInstructions[i].Instr << " " <<QInstructions[i].Length << " " << QInstructions[i].Code << endl;
return QInstructions[i].Code;
break;
}
return QNONE;
}
int main(int argc, const char * argv[]) {
string Key = "QKey2";
cout << FindCode(Key);
}

In your code
vector<QKeys> QInstructions={
("QKey1",6,QKey1),
{"QKey2",5,QKey2}
};
the first line of data is using parenthesis "()". Replace them with accolades "{}" and it will work.
Also, i see you have written unsigned index = (unsigned int)-1;. This is undefined behavior according to the standard. This is also bad because you are using a C-style cast (see here). You should replace it with:
unsigned index = std::numeric_limits<unsigned int>::max();

Finally, I found the right solution as
Initialize a vector of customizable structs within an header file . Unfortunately, replacing parenthesis did not help.
Concerning setting an unsigned int to its highest possible value using -1, I find as overkill to use std::numeric_limits<unsigned int>::max() for such a case, a kind of over-standardization. I personally think that as long as we are using two's complement representation, the assignment will be correct. For example, at
http://www.cplusplus.com/reference/string/string/npos/
you may read:
static const size_t npos = -1;
...
npos is a static member constant value with the greatest possible
value for an element of type size_t.
...
This constant is defined with a value of -1, which because size_t is
an unsigned integral type, it is the largest possible representable
value for this type.

Related

Weird type assignment for array index in C++

Hi I have a sample program
#include <iostream>
int main() {
int a = -5;
int arr[a];
std::cout << "Size of arr: " << sizeof(arr) << std::endl;
return 0;
}
Here I am getting the output of 17179869164.
My question is that the array size value should not accept negative values! and if I try giving a[-5], it throws an error. but now how am I getting the output of 17179869164.
I have my assumption too, the -5 is converted to an unsigned int value of 4294967291 and the total size is given as 17179869164 = 4294967291 * 4(size of int).
So I wanted to know why the compiler is typecasting signed int to unsigned int and not throwing a compile-time error. I needed a clear understanding of how the compiler is executing that piece of code?
It is something called undefined behavior. To catch that kind of bug you could use the help of a static analyser.
Someone else asked something similar here:
Declaring an array of negative length
For C++, Variable Length Arrays are not provide by the standard, but may be provided by compiler extension. For C, the short answer is the standard converts the value to a positive integer value unless it is a constant expression -- in your case resulting in the use of the unsigned value (use of the two's compliment value as a positive value). Specifically:
C11 Standard - 6.7.6.2 Array
declarators(p5)
If the size is an expression that is not an integer constant
expression: if it occurs in a declaration at function prototype scope,
it is treated as if it were replaced by *; otherwise, each time it is
evaluated it shall have a value greater than zero.
I noticed some interesting behavior in GodBolt.
I took you code and added a second copy where a is declared constant:
#include <iostream>
int foo() {
int a = -5;
int arr[a];
std::cout << "Size of arr: " << sizeof(arr) << std::endl;
return 0;
}
int bar() {
const int a = -5;
int arr[a];
std::cout << "Size of arr: " << sizeof(arr) << std::endl;
return 0;
}
Then I threw GCC, Clang, and MSVC at them.
As far as I know, GCC and Clang both support variable length arrays (VLAs) as an "extra feature", and they both ate foo without a single complaint. Whereas MSVC, who does not support VLAs, complained.
On the other hand, none of them accepted bar on account of a being negative.
As for why GCC and Clang can't tell that ais negative in foo, that I will leave as a question for people more versed in compiler guts than I.

why int a= 4i; not report an syntax error(c++)

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
int a = 232u;
int b = 4i;
cout << a << endl << b;
}
I was review basic of cpp, As the screen shot I took, I tried to sign an unsigned int to a int which was fine, then I tried change that u to i and waiting for a error, but there's no error and output was 0. There's no define of i. So what happened.
I'm using xcode on mac, last picture is the build settings.
C++ has a concept of literals, this is used to describe the type of a value. For example, integer literal can be used to write I want a integer 1 with a type unsigned int. We will write it 1u.
In your case, your are probably using a GNU extension for imaginary constants. What you write don't compile in C++ standard.
The good way to use complex literal in C++ standard is to include include <complex>. And to use std::complex_literals, this is only possible in C++14.
The suffix i denotes the imaginary part of a complex number; when assigning an (implicitly) constructed complex number to integral value, only the real part is taken.
Hence, the following expression yields 0:
int b = 4i; // gives 0; real-part of 4i is 0, imaginary-part is 4: casting to int gives the real part, i.e. 0
But:
int x = 4i*4i; // gives -16; as i means the square root of -1, i*i yields -1; so 4i*4i = -16
Note that this works even without including <complex>.

Using pointers to members and macros

I'm having problems with the following code:
#include<iostream>
#include<utility>
#define Row *prow
#define Col *pcol
typedef unsigned int uint;
typedef std::pair<uint, uint> Node;
uint Node::Row = &Node::first;
uint Node::Col = &Node::second;
int main()
{
Node node(1,2);
std::cout << node.*prow << node.*pcol << '\n'; // OK
std::cout << node.Row << node.Col << '\n'; // doesn't compile
}
The idea was to use std::pair but replace first and second with other names, in that case Row and Col. However, the last line doesn't compile even though it should be exactly the same as the line before it. I'd really appreciate if someone could explain me why it happens. I'm using VS2015.
Edit: compiler error C2059 syntax error:'*'
.* is a single token. Your macro is generating two adjacent tokens, . and *, which is not the same thing. (Or at least it might do. Almost certainly you're invoking undefined behaviour.)
There's probably a solution involving token pasting, but you'd do yourself a big favour (and make Bjarne happy) by just not using macros in C++.

Return Wrap of size_t in Rcpp

I am new to Rcpp so still blindly finding my way around. The long and the short of the problem is that I have an object that generates a pointer and I want that pointer returned to R.
I find that casting the pointer to a size_t maintains the necessary precision, however, I seem not to be able to return that with wrap.
In the code below, only returning the unsigned long int will compile, the others throw errors, which for the sake of space I will not include here. And with my object, casting to an unsigned long int causes the compiler to fail due to precision lost (that's in the first block that is all commented out).
Using a size_t should suffice for my needs as to avoid the alternative of creating a wrap template for this type of object.
I checked the changelog and it seems that size_t should be supported. The overview also suggests wrap support for size_t.
#include <Rcpp.h>
#include <iostream>
using namespace Rcpp;
using namespace std;
extern "C" SEXP attempt()
{
// this block if uncommented gives compile error that converting a pointer to unsigned long int loses precision
// also, wrapping the pointer &f causes a compilation error
//int f = 314;
//unsigned long int theVar_longint = (unsigned long int) &f;
//cout << "pointer: " << &f << endl;
//return(wrap(&f));
// This block makes an arbitrary value into a size_t, unsigned long int and unsigned long long int
size_t theVar_sizet = (size_t) 383762523;
unsigned long int theVar_longint = (unsigned long int) 383762523;
unsigned long long int theVar_longlongint = (unsigned long long int) 383762523;
// prints the results
cout << "size_t: " << theVar_sizet << endl;
cout << "longint: " << theVar_longint << endl;
cout << "longlongint: " << theVar_longlongint << endl;
// only the first line returns properly, the others cause errors in compilation
return(wrap(theVar_longint));
//return(wrap(theVar_longlongint));
//return(wrap(theVar_sizet));
}
What size_t, long int and long long int actually are depend on the platform, so I would advise against relying on them, i.e. wrapping them out to the R side.
We attempted to supprt 64 bit integer types by using the int64 package, but this has caused some issues, which will get fixed. When this is done, you will be able to wrap out either 32 bit integers (int) or 64 bits integers (int64_t). I would discourage using size_t, long or long long.
I am a little confused: A pointer, by definition, points to a (transient ?) memory location. Why would you return a pointer to R?
There is one very clearly defined use case, and that involves the R type 'external pointer' (discussed in the Writing R Extensions manual in Section 5.13). To name a few examples, R's external pointers are used by packages like RODBC to control the (external) database connection object, by bigmemory to work with external memory and by my own RcppDE to hand a compiled objective function down to the differential evolution optimization routine. All these uses make sense to me---and we have the Rcpp::XPtr type to support it---but just passing a pointer around does not.
Can you explain more clearly why you'd need a pointer?
(Also, if you tried to post on rcpp-devel, make sure that your From: address is exactly the same as the address you subscribed with.)

Issue with vector<bool> and printf

#include <vector>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, const char *argv[])
{
vector<bool> a;
a.push_back(false);
int t=a[0];
printf("%d %d\n",a[0],t);
return 0;
}
This code give output "5511088 1". I thought it would be "0 0".
Anyone know why is it?
The %d format specifier is for arguments the size of integers, therefore the printf function is expecting two arguments both the size of an int. However, you're providing it with one argument that isn't an int, but rather a special object returned by vector<bool> that is convertible to bool.
This is basically causing the printf function to treat random bytes from the stack as part of the values, while in fact they aren't.
The solution is to cast the first argument to an int:
printf("%d %d\n", static_cast<int>(a[0]), t);
An even better solution would be to prefer streams over printf if at all possible, because unlike printf they are type-safe which makes it impossible for this kind of situation to happen:
cout << a[0] << " " << t << endl;
And if you're looking for a type-safe alternative for printf-like formatting, consider using the Boost Format library.
%d format specifier is for int type. So, try -
cout << a[0] << "\t" << t << endl;
The key to the answer is that vector isn't really a vector of bools. It's really a vector of proxy objects, which are translatable into ints & bools. This allows each bool to be stored as a single bit, for greater space efficiency (at the cost of speed efficiency), but causes a number of problems like the one seen here. This requirement was voted into the C++ Standard in a rash moment, and I believe most committee members now believe it was a mistake, but it's in the Standard and we're kind-of stuck with it.
The problem is triggered by the specialization for bool of vectors.
The Standard Library defines a specialization of the vector template for bool. The description of this specialization indicates that the implementation should pack the elements so that every bool only uses one bit of memory. This is widely considered a mistake.
Basically std::bool use 1 bit instead of 1 byte, so you face undefined behavior regarding printf.
If you are really willing to use printf, you can solve this issue by defining std::bool as char and print it as integer %d (implicit conversion, 1 for true and 0 for false).
#include <vector>
#include <iostream>
#include <stdio.h>
#define bool char // solved
using namespace std;
int main(int argc, const char *argv[])
{
vector<bool> a;
a.push_back(false);
int t = a[0];
printf("%d %d\n", a[0], t);
return 0;
}