When I make my own struct, say:
struct myStruct{
int data1;
int data2;
string data3;
}
I can initialize an instance of type myStruct like this:
myStruct instance1;
So my question is, why am I often seeing "struct" written during the initialization of a struct?
Maybe that's an inaccurate statement so here is an example of what I mean:
/*This is a tiny program that checks
to see if a file exists in
the current working directory. */
#include <sys/stat.h>
#include <iostream>
using namespace std;
const string FILENAME = data.txt;
int main(){
struct stat fileStatus; //<-- HERE HERE HERE!
if (FileExists(FILENAME, fileStatus)){
cout << "File Does Exist" << endl;
}else{
cout << "File Does NOT Exist" << endl;
}
return 0;
}
bool FileExists(const string & fileName,struct stat & fileStatus){
bool fileDoesNotExist = stat (fileName.c_str(), &fileStatus);
return !fileDoesNotExist;
}
>
LINE 13: struct stat fileStatus;
Is this something that was done in C for some reason?
Something with a macro or a typedef?
I just don't understand why this is the way it is.
This is a C thing; there's no good reason to continue to do it in C++.1
In C, struct is part of the typename, e.g.:
struct foo { int x; };
defines a type called struct foo. In C++, it defines a type called foo. In C, you can usually hide this irritation behind a typedef:
typedef struct foo { int x; } foo;
1 At least, not in code that couldn't possibly also be compiled as C (such as the example in your question).
You can do what you want by instead calling it like this:
typedef struct mystruct
{
int itema;
int itemb;
Etc...
}* mystruct;
So that's whenever you make a mystruct item it creates a pointer to your struct, else you have to call your struct by
struct mystruct *object;
Related
Following codeblock is compiling and running okay.
Qeus-1. Is it safe to memset a struct which contains another stuct with smart pointer as a member variable? (like the example code below)
Ques-2. Is it safe to memset a struct which contains smart pointer members?
Following code structure is part of a legacy project where this hierarchical structures have hundreds of other members (POD or non POD memebers)
#include <iostream>
#include <map>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <memory>
typedef struct _Globals{
std::shared_ptr<std::map<int, std::string> > rollNamePair;
} _Globals;
struct _Class {
struct _Globals Globals; // global vars
};
struct _School {
struct _Class *pSchool;
};
int main()
{
struct _School abc;
memset(&abc, 0, sizeof(struct _School));
abc.pSchool= (struct _Class*) malloc(sizeof(struct _Class));
abc.pSchool->Globals.rollNamePair= std::make_shared<std::map<int, std::string> >();
(*abc.pSchool->Globals.rollNamePair)[1]= "John";
(*abc.pSchool->Globals.rollNamePair)[2]= "Paul";
std::cout << (*abc.pSchool->Globals.rollNamePair)[1] << "\n";
std::cout << (*abc.pSchool->Globals.rollNamePair)[2];
return 0;
}
No, never use memset on any structure which is not POD.
However your code isn't doing that, it is only calling memset on _School which is POD as it only contains a pointer, calling memset on _Class or _Globals would have undefined behaviour. However I'd prefer removing the memset and adding a constructor to _School which initialises pSchool to nullptr:
struct _School {
_Class *pSchool;
_School() : pSchool(nullptr) {}
};
You need to use new in C++ code rather than malloc as malloc doesn't call class constructors.
Also note that identifiers starting with underscore followed by an uppercase character are reserved for use by the compiler/standard library.
The complete code would be:
#include <map>
#include <string>
#include <memory>
#include <iostream>
struct Globals{
std::shared_ptr<std::map<int, std::string> > rollNamePair;
};
struct Class {
Globals Globals; // global vars
};
struct School {
Class *pSchool;
School() :pSchool(nullptr) {}
};
int main()
{
School abc;
abc.pSchool= new Class();
abc.pSchool->Globals.rollNamePair = std::make_shared<std::map<int, std::string> >();
(*abc.pSchool->Globals.rollNamePair)[1] = "John";
(*abc.pSchool->Globals.rollNamePair)[2] = "Paul";
std::cout << (*abc.pSchool->Globals.rollNamePair)[1] << "\n";
std::cout << (*abc.pSchool->Globals.rollNamePair)[2];
delete abc.pSchool;
return 0;
}
To address the second question, if you have a struct
struct G {
std::shared_ptr<T> ptr;
};
that contains a smart pointer as its member, then doing
G g;
std::memset(&g, 0, sizeof(G));
is definitely not safe, because you overwrite g.ptr object of a non-POD type that has already been constructed.
What you could do is something like this:
std::aligned_storage_t<sizeof(G), alignof(G)> storage; // Raw storage of some POD type
std::memset(&storage, 0, sizeof(G));
auto g = new (&storage) G;
g->ptr = std::make_shared ... ;
// ...
std::destroy_at(g);
There is no reason to use memset in this particular example, but it is legal and safe.
I'm beginning to learn C++. In the IDE codeblocks, this compiles:
#include <iostream>
using namespace std;
struct A {};
struct B {
A a;
}
void hi() {
cout << "hi" << endl;
}
int main() {
hi();
return 0;
}
But this doesn't:
struct B {
A a;
}
struct A {};
int main() {
hi();
return 0;
}
void hi() {
cout << "hi" << endl;
}
It gives me the errors:
error: 'A' does not name a type
error: 'hi' was not declared in this scope
Should class/function order matter in C++? I thought it doesn't. Please clarify the issue.
Yes, you must at least declare the class/function before you use/call it, even if the actual definition does not come until afterwards.
That is why you often declare the classes/functions in header files, then #include them at the top of your cpp file. Then you can use the classes/functions in any order, since they have already been effectively declared.
Note in your case you could have done this. (working example)
void hi(); // This function is now declared
struct A; // This type is now declared
struct B {
A* a; // we can now have a pointer to it
};
int main() {
hi();
return 0;
}
void hi() { // Even though the definition is afterwards
cout << "hi" << endl;
}
struct A {}; // now A has a definition
I have some C code that has some structs that looks like this:
typedef struct my_library_a_t my_library_a_t;
typedef struct my_library_b_t my_library_b_t;
typedef struct my_library_c_t my_library_c_t;
struct my_library_a_t {
struct my_library_b_t {
int data;
struct my_library_c_t {
int data;
} c;
} b;
int data;
};
This doesn't work in C++, because in C struct my_library_b_t defines a global struct my_library_b_t, whereas in C++ it defines ::my_library_a_t::my_library_b_t.
How can I get the inner struct definition to define a global struct in C++? Or even just not have to change too much code for it to work (I don't mind having a #ifdef __cplusplus block, but I don't want to pull the structs out because the reason they are nested in the first place is that they are used only one time each, and it's really hard to read when the inner class definitions are above the outer class definitions)
I tried struct ::my_library_b_t in the definition, but this doesn't work.
For context, I'm parsing a string that has a definition that would look like this:
a = b "," data
b = data "," c
c = data
data = %x31-39 *DIGIT ; 1-9 followed by *(0-9)
/ "0"
And the intermediate parts have meaning, so it's useful to be able to have functions that take my_library_b_t* or my_library_c_t*.
I would prefer to have a solution that looks like this:
#ifdef __cplusplus
#define GLOBAL_STRUCT(name) ??? (I tried `:: name`)
extern "C" {
#else
#define GLOBAL_STRUCT(name) name
#endif
struct my_library_a_t {
struct GLOBAL_STRUCT(my_library_b_t) {
// ...
I recommend this
struct my_library_a_t {
struct my_library_b_t {
int data;
struct my_library_c_t {
int data;
} c;
} b;
int data;
};
#ifdef __cplusplus
typedef struct my_library_a_t::my_library_b_t my_library_b_t;
typedef struct my_library_b_t::my_library_c_t my_library_c_t;
#else
typedef struct my_library_a_t my_library_a_t;
typedef struct my_library_b_t my_library_b_t;
typedef struct my_library_c_t my_library_c_t;
#endif
Notice that after alias my_library_b_t, you don't need to use my_library_a_t::my_library_b_t::my_library_c_t
I want to put constants in a struct, but compiler generates error that ";" is missing at the "=".
struct {
int aaa=111; // error: "expected ; at end of declaration list"
} blah;
Did you try maybe:
int aaa{111};
And if you need int as a constant you should probably include the const keyword.
const int aaa{111};
You can't initialize at the time of defining the structure in Obj-C. Initialization is possible at the time of creating instance shown as below.
struct Employee {
int idNumber;
int age;
};
// create instance
struct Employee emp1;
emp1.idNumber=12345;
emp1.age = 25;
If you're using Objective-C, in an .h file add something like:
extern const struct MyStruct {
int aaa;
} MyStruct;
In the .m file:
const struct MyStruct MyStruct = {
.aaa = 1
};
#import the .h file and use the struct in your code like this:
if (someInteger == MyStruct.aaa) ...
The question is rather simple: how to pretty print the name of a template parameter in a C++ class and assign it to a class variable at compile time ?
It seems that both typeinfo (typeid) and boost::typeindex must be evaluated at runtime or as least some part of them. This apparently does not allow the compiler to completely solve a constexpr containing a call to one of this function.
template<typename T>
class X
{
public:
static const char * name = /* SOME C++ code transforming T in a string (either std::string or char */
};
What am I missing ?
Is it only possible to generate a name at runtime ? In that case, does I really need an instantiated object ? It doesn't seem right to me, because the following perfectly work without any instance:
#include <iostream>
#include <string>
#include <boost/type_index.hpp>
using namespace std;
template<class T>
class X
{
public:
static std::string name()
{
return boost::typeindex::type_id<T>().pretty_name();
}
};
struct foobar {};
int main()
{
cout << X<int>::name() << endl;
cout << X<foobar>::name()<< endl;
}
So instead of having name() as a class method, I'd like to have it as a class variable.
I think, it is possible to use custom Type Traits. Please see the next example:
#include <iostream>
#include <string>
using namespace std;
//Using stub type traits
template <class T>
struct TypeTraits;
//your TypeTraits for specific types...
template<>
struct TypeTraits<int>
{
constexpr static const char *name = "int";
};
template<class T>
class X
{
public:
constexpr static const char * name = TypeTraits<T>::name;
};
struct foobar {};
//TypeTraits for custom foobar
template<>
struct TypeTraits<foobar>
{
constexpr static const char *name = "foobar";
};
int main()
{
//Now you can use static member here
cout << X<int>::name << endl;
cout << X<foobar>::name<< endl;
}
Also TypeTraits can be used (and expanded) for other purposes.