How to initialize a struct with union? - c++

How can I properly initialize a struct which contains a union? Currently I get an error // error C2440: 'initializing': cannot convert from 'float' to 'const char *'
#include <stdio.h>
using namespace std;
typedef enum {STRING, REAL, POINTER } Type;
const struct Entry {
union {
const char *string;
float real;
void *pointer;
};
Type type;
LPCSTR Key;
LPCSTR Name;
}f;
const Entry Entries[] = {
{{0.5f}, REAL, "Key", "Name" } // error C2440: 'initializing': cannot convert from 'float' to 'const char *'
};
int main(int argc, char **argv)
{
for (int i = 0; i < size(Entries); i++)
{
switch Entries[i].type
{
case STRING:
printf("Type string; Value: %s\n", Entries[i].string);
case REAL:
printf("Type string; Value: %d\n", Entries[i].real);
}
}
}

When initializing a union, only the first member will be initialized. Rearrange the union so that float real becomes the first member of the union.
Of course, that means you can't use the other members in direct initialization.
The other solution is to add a constructor to the union, like one for the real member, one for the string member and one for the pointer member.

What is the reason You want to use union? Unions are great for saving memory. In c++ rarely there is a need to use them.
I know that is not the answer for your question but think if You have to use them in this project.

Related

Can not define struct type: member name not declared

I try to define a struct type in C++ in the following way:
struct fckxMsg_t {
unsigned char : status;
unsigned char : data1;
unsigned char : data2;
};
My compiler complains with:
error: 'status' was not declared in this scope unsigned char : status;
I don't see what is wrong. Actually I just want to give the members a name. Why should it have been declared before???
Thanks for your quick response!
The correct code should be:
struct myStruct {
unsigned char status;
unsigned char data1;
unsigned char data2;
};
I can now jump to my next bug :-))

How do you C++ Vector init in header construct to fill with pointers of a static char const

header file:
#include<vector>
#ifndef FOO_H
#define FOO_H
class Foo
{
public:
Foo(int s) : pegs (s, *TOKEN_EMPTY){}
static char const TOKEN_EMPTY=' ';
protected:
std::vector<char*> pegs;
}
When trying to build I get the error:
error: invalid type argument of unary ‘*’ (have ‘char’)
20 | Foo(int s) : pegs (s, *TOKEN_EMPTY){}
In case it isn't clear, I just want to initialize a C++ vector of pointers that point to a static char const variable.
I'm still checking StackOverflow and online, but I am hopeful someone can help me or lead me in the right direction!
Adding few more points in the answer provided by #Roger.
*TOKEN_EMPTY is incorrect syntax, what you need is address of TOKEN_EMPTY so you need to apply & operator to get address of the variable.
the TOKEN_EMPTY is const char string, so when you apply & operator, it would return const char*. So you need to update your vector to hold const char *.
Alternatively you can also use typecast operation to convert const char * to char * but it could possibly lead to issues where you can potentially modify the value of const char.
Here is a sample code.
#include <iostream>
#include <vector>
class Foo
{
public:
Foo(int s) : pegs (s, &TOKEN_EMPTY){}
static char const TOKEN_EMPTY=' ';
protected:
std::vector<const char*> pegs;
};
int main() {
// ues class Foo
return 0;
}
Changed to &TOKEN_EMPTY and had to use:
std::vector<const char*> pegs;

Declare unsigned char[] with Q_DECLARE_METATYPE

I'm trying to set up some unit tests with QtTest and i'd like to use QFETCH.
I am testing the following function :
static std::vector<bool> FrameHandler::getBitsFromFrame(unsigned char* data, unsigned char length);
It simply converts a array of char into a vector of bits.
So, I set up my test class like this :
#include <QtTest/QtTest>
#include <vector>
#include "FrameHandler.h"
class BusTester : public QObject {
Q_OBJECT
private slots:
void bytesToVector_data() {
QTest::addColumn<unsigned char[]>("Tested");
QTest::addColumn<unsigned char>("Length");
QTest::addColumn< std::vector<bool> >("Reference");
// Test for one byte
std::vector<bool> oneByte(8, false);
oneByte[0] = true;
oneByte[1] = true;
oneByte[3] = true;
oneByte[4] = true;
unsigned char oneByteInput[1]{
0b11011000
};
QTest::newRow("One byte") << oneByteInput << 1 << oneByte;
}
void bytesToVector() {
QFETCH(unsigned char[], tested);
QFETCH(unsigned char, length);
QFETCH(std::vector<bool>, reference);
QCOMPARE(FrameHandler::getBitsFromFrame(tested, length), reference);
}
};
QTEST_MAIN(BusTester)
#include "bustester.moc"
When I do this, the compiler says :
expected unqualified-id before ‘[’ token
QFETCH(unsigned char[], tested);
And also :
On line `QTest::addColumn<unsigned char[]>("Tested");`, Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system
I thought the two errors were linked, so i added Q_DECLARE_METATYPE(unsigned char[]); before the class declaration, but then I get this :
In qmetatype.h, expected '>' before '*' token (line 1695)
Is it possible to declare unsigned char[] to Qt's QMetaType system ?
Thanks
Q_DECLARE_METATYPE(T) Type T must be constructable, copiable and destructable.
Array doesn match this rules, but you can create wrapper around.
struct Arr
{
unsigned char arr[SIZE];
};
Q_DECLARE_METATYPE( Arr );
or
typedef std::array<unsigned char, SIZE> TArr;
Q_DECLARE_METATYPE( TArr );
But there is one difficulties - SIZE, You have-to declare it

cannot convert 'int (B::*)(std::string)' to 'int (*)(std::string) ' in assignment pt2function=&B::generate_callback;

I am new to c++, .I am trying to create a pgm that contains 2 classes ,out of which one class has a member function that would generate a callback function in another class though a function pointer, but i keep getting the following error.
#include <iostream>
#include <string>
using namespace std;
class B
{
private: std::string str1;
public: int generate_callback(std::string str1);
};
int B::generate_callback(std::string str1)
{
if ((str1=="Generate")||(str1=="generate"))
{
Cout<<"Callback generated ";
}
return 0;
}
class A : public B
{
public:
void count(int a,int b);
private: int a,b;
};
void A::count(int a, int b)
{
for ( a=1;a<b;a++){
if(a==50)
{
cout<<"Generating callback ";
goto exit;
}
exit: ;
}
}
int (*pt2function)(string)=NULL;
int main()
{
B obj1;
A obj2;
string str;
cout<<"To generate callback at int i=50 please enter 'generate'";
cin>>str;
obj2.count(1,100);
pt2function=&B::generate_callback;
(obj1.*pt2function)(str);
return 0;
}
The errors :
main.cpp:57: error: cannot convert 'int (B::*)(std::string) {aka int (B::*)(std::basic_string<char>)}' to 'int (*)(std::string) {aka int (*)(std::basic_string<char>)}' in assignment
pt2function=&B::generate_callback;
/home/adt/practice/N_practise/n_pract_2/pract2/main.cpp:58: error: 'pt2function' cannot be used as a member pointer, since it is of type 'int (*)(std::string) {aka int (*)(std::basic_string<char>)}'
(obj1.*pt2function)(str);
^
^
The variable pt2function is a pointer to a non-member function. Such a pointer is not compatible with a pointer to a member-function. Which is what the compiler tells you with the first error: A int (*)(string) is not compatible with a int (B::*)(string).
You need to define pt2function as a pointer to a B member function:
int (B::*pt2function)(string)=NULL;
Now you can initialize or assign a matching member function of B to the variable pt2function.
This also solves the second errors, which basically says that in your current code the variable pt2function is not a pointer to a member function, and therefore can not be used as such.
Pointers to functions and pointers to member functions are really different beasts.
You have mainly two options to get it working in your code:
Change this line:
int (*pt2function)(string)=NULL;
To this:
int (B::*pt2function)(string)=NULL;
That is defining pt2function as a pointer to a member function of B that gets a string and returns an int.
Declare the generate_callback as a static method and invoke it as pt2function(str); in your main function.
In fact, a static member function can be assigned to a pointer to function like the one you have already in use.

Require Help Resolving error C2664

I have the following code which is giving me this error
main.cpp(41): error C2664: 'std::pair std::make_pair(_Ty1,_Ty2)' : cannot convert argument 1 from 'Handle' to 'unsigned int &'
My example program is
#include <vector>
#include <utility>
typedef unsigned int u32;
typedef u32 Handle;
struct File
{
File()
: ch(0),
pageIdx(0)
{
}
Handle ch : 8;
u32 pageIdx;
};
int main() {
std::vector<std::pair<Handle, u32> > toTrim;
toTrim.reserve(64);
File* m_pFirstPage = new File();
File* pRef = m_pFirstPage;
toTrim.push_back(std::make_pair(pRef->ch,pRef->pageIdx));
return 0;
}
When I try to static cast i.e
toTrim.push_back(std::make_pair(static_cast<unsigned int>(pRef->ch), pRef->pageIdx));
I get the following error
main.cpp(41): error C2664: 'std::pair std::make_pair(_Ty1,_Ty2)' : cannot convert argument 1 from 'unsigned int' to 'unsigned int &'
Can someone please help me resolve it and explain what I am doing wrong.
What is happening is that you are specifying bit fields with the : 8 notation.
More info at:
http://www.tutorialspoint.com/cprogramming/c_bit_fields.htm
That creates a pseudo-char field on your handle variable of 8 bits instead of 32 as typedef u32 Handle defines. std::make_pair requires passing it's arguments by reference.
Since Handle ch : 8 is different type from Handle you can't pass it by reference because is considered undefined behavior cast a variable that is pass by reference.
More info at:
How to cast a variable member to pass it as reference argument of a function
If you need the : 8 field you may use an extra variable to create the pair correctly.
#include <vector>
#include <utility>
typedef unsigned int u32;
typedef u32 Handle;
struct File
{
File()
: ch(0),
pageIdx(0)
{
}
Handle ch : 8; //Different type than just Handle
u32 pageIdx;
};
int main() {
std::vector<std::pair<Handle, u32> > toTrim;
toTrim.reserve(64);
File* m_pFirstPage = new File();
File* pRef = m_pFirstPage;
unsigned int ch_tmp = pRef->ch; //<-Extra variable here
toTrim.push_back(std::make_pair(ch_tmp, pRef->pageIdx));
return 0;
}