Struct with Vector of Structs - c++

Sorry, the title sounds a little confusing, let me explain.
I have a struct, which has a vector of structs, like this:
struct foo {
int x;
vector < foo > bar;
};
But I get an error of "No Instance of Overloaded Method" when I try this syntax:
foo a;
foo b;
b.x = 3;
a.bar.push_back(b);
Basically, I am just trying to create a "relationship" between a and b, with bar being the relationship vector containing all related instances of foo.
Any suggestions?

Your code is, unfortunately, illegal according to the C++ Standard, because you are passing an incomplete type as a template parameter to the Standard Library, which is prohibited in general and std::vector doesn't have an exception to the general rule.
The Boost documentation has a great explanation.
You can either use a container which explicitly supports incomplete types, as the Boost ones do, or use std::vector<std::unique_ptr<foo>>, because the Standard says in 20.9.1p5:
The template parameter T of unique_ptr may be an incomplete type.

May be it's your compiler, Mine gives no error or warnings.
#include <iostream>
#include <vector>
using namespace std;
struct foo {
int x;
vector < foo > bar;
};
int main()
{
foo a;
foo b;
b.x = 3;
a.bar.push_back(b);
cout<<a.bar[0].x;
cout<<"\n";
return 0;
}

Related

Pass enum in a scope to another as function argument

How to pass enum in a scope to another as function argument? As this is failing:
enum class L;
struct TestClass
{
void foo(L n)
{
int v = static_cast<int>(n);
int r[v] = { 9 };
cout << "\n" << v << "\n";
}
};
int main()
{
enum class L : int
{
A, B, C, D
};
TestClass main;
main.foo(L::D);
return 0;
}
error: cannot convert ‘main()::L’ to ‘L’
80 | main.foo(L::D);
| ~~~^
| |
| main()::L
How to solve this (in exact place, not move enum to a scope else) ?
How to solve this (in the exact place, not move enum to a scope else)?
Cast the enum while passing as a parameter.
main.foo(static_cast<int>(L::D));
Then your member function would be
void foo(int n)
{
std::vector<int> r(n, 9); // used `std::vector` instead of VLA
std::cout << "\n" << n << "\n";
}
(See sample code)
Note that the VLAs are not part of standard C++. Read more in the following post:
Why aren't variable-length arrays part of the C++ standard?
Prefer using std::vector as shown in the above code sample.
In a nutshell, the problem is that you have an enum that you want to use in two places. To me, the most natural solution to this is to put the enum in its own header file and use it where it is required.
// my_enum.h
#pragma once
enum class L : int {
A, B, C, D
};
// TestClass.h
#pragma once
// Can forward declare L so long as we define the functions in the same cpp
// If original enum is in a namespace it needs to be forward declared in the same namespace
enum class L;
struct TestClass {
void foo(L n);
};
// TestClass.cpp
#include "TestClass.h"
#include "my_enum.h"
void TestClass::foo(L n)
{
// do stuff with n
}
// main.cpp
#include "TestClass.h"
#include "my_enum.h"
int main(){
TestClass main;
main.foo(L::D);
return 0;
}
How to solve this (in exact place, not move enum to a scope else) ?
I'm conscious that I've answered the question in a way you did not want, but I do not see why you wouldn't want to put the enum in its own file. Avoiding this will lead to problems at some point. The consequence of JeJo's solution is that you could pass any old integer in to foo() - it is essentially decoupled from the enum. If the integer value is supposed to originate from the enum L: 1) it isn't obvious from the function signature and 2) it is prone to misuse i.e. someone passing in a value they shouldn't.
If putting the enum in its own header file is an unacceptable solution, I'd be interested to know why.

How can I declare a struct?

I am currently learning C++ and trying to understand the usage of structs.
in C++. As far as I'm aware, if you want to define a function after the main() function, you have to declare it beforehand, like in this function (Please tell me if I'm wrong with it):
#include "stdafx.h"
#include <iostream>
#include <string>
void printText(std::string); // <-- DECLARATION
int main()
{
std::string text = "This text gets printed.";
printText(text);
}
void printText(std::string text)
{
std::cout << text << std::endl;
}
My question now is if there is a way to do the same with structs. I don't want having to always define a struct before the main() function, just because I prefer it like that. However, I get an error when I try doing it like that:
//THIS program DOESN'T work.
#include "stdafx.h"
#include <iostream>
#include <string>
struct Products {std::string}; // <-- MY declaration which DOESN'T work
int main()
{
Products products;
products.product = "Apple";
std::cout << products.product << std::endl;
}
struct Products
{
std::string product;
};
When I delete the decleration and instead define the struct before the main function, the program works so I assume I'm somehow wrong with the decleration:
//THIS program DOES work
#include "stdafx.h"
#include <iostream>
#include <string>
struct Products
{
std::string product;
};
int main()
{
Products products;
products.product = "Apple";
std::cout << products.product << std::endl;
}
Could someone tell me if there is some way to declare a struct like that? Bear with me if I have any major mistake in the code, I'm just a beginner.
Thanks in advance!
You can pre-declare (forward-declare) a class type in C++.
struct Products;
However, a class type declared in this way is incomplete. Incomplete types can only be used in a number of very limited ways. You will be able to declare pointers or references to such type, you will be able to mention it in non-defining function declarations etc., but you will not be able to define objects of such incomplete type or access their members.
If you want to define objects of class Products or access members of class Products, you have no other choice but to fully define the class before such use.
In your case you are defining an object of type Products in main as well as accessing members of class Products there. This means that you have to completely define Products before main.
In your particular case a forward declaration wont help, because a forward declaration only allows you to use pointers or references, as e.g. in
struct foo;
foo* bar(foo f*) { return f;}
struct foo { int x; }
However,
struct Products {std::string};
is not a declaration, but if you want an ill-formed declaration and definition.
The correct forward declaration would be:
struct Products;

Is there another reason for using tags in typedef except for self referencing?

If I want to create a new struct type that contains a pointer the type itself I wouldn't be able to do
typedef struct {
my_type* p;
} my_type;
and I will need to use a tag
typedef struct my_tag {
struct my_tag* p;
} my_type;
Is there another use for the tag mechanism? because I've seen it several times and I don't understand why someone would add this to a typedef
Also, since C and C++ are a bit different with their struct keyword, would that change anything if I typedef such a struct in C or in C++?
Another use is "opaque type", which is usually forward- declared as
typedef struct my_type my_type;
where you want to define a type at the same time as you do a forward declaration. typedef struct my_type; would have been nonsense. In general, you can't forward-declare without a struct tag.
I looked over the comments and answer, but never saw this. It seems too obvious for someone to not have already brought it up, so I apologize if this duplicates a response.
In C++, you don't use typedef struct. Instead, add a forward declaration of the incomplete type to the member's declaration:
#include <iostream>
struct my_type {
int i;
struct my_type* p;
};
int main() {
my_type my_obj;
my_obj.i = 100;
my_obj.p = &my_obj;
std::cout << my_obj.p->i << '\n';
}

A confusing typedef involves class scope

I'm reading code of a C++ project and it contains some code of the following form:
namespace ns {
class A {};
class B {};
}
struct C {
typedef ns::A* ns::B::* type;
};
Can someone explain the meaning of the typedef line? type seems to be some kind of pointer to member of ns::B which points to ns::A, but I'm not sure.
Class A and B in the real code are not empty, but I think it's not relevant here. And here is a live example.
ns::B::*
is a pointer-to-member-variable of B. Then ns::A* is its type.
So the whole declaration means
pointer-to-member-variable of B of type ns::A*
The answer by #vsoftco already answers the core of the question. This answer shows how one might use such a typedef.
#include <iostream>
#include <cstddef>
namespace ns {
struct A {};
struct B
{
A* a1;
A* a2;
};
}
struct C {
typedef ns::A* ns::B::*type;
};
int main()
{
C::type ptr1 = &ns::B::a1;
C::type ptr2 = &ns::B::a2;
ns::B b1;
b1.*ptr1 = new ns::A; // Samething as b1.a1 = new ns::A;
return 0;
}

Define object from template type

is there any way to define an object in a way similar to the line below???
template<typename T>
struct A {
T *data;
//...
typedef T data_type;
};
int main() {
A<int>::data_type a; // ok
A<int> obj;
obj.data_type b; // <-- is it possible to do something like this??
}
Thanks!
Massimo
You can use decltype on expressions. The code for your case would be:
decltype(obj)::data_type b;
From C++11 onwards it is possible:
decltype(obj) is evaluated at compile-time and is the type of obj. It can be used whenever a type is used.
So you could write decltype(obj)::data_type b;
decltype is a keyword and is particularly useful in generic programming.
This seems to work fine; use decltype() for c++11; you can try typeof() pre c++11
typeof() in gcc: https://gcc.gnu.org/onlinedocs/gcc/Typeof.html
#include <iostream>
using namespace std;
template<typename T>
struct A {
T *data;
//...
typedef T data_type;
};
int main() {
A<int>::data_type a; // ok
A<int> obj;
decltype(obj)::data_type b; // <-- is it possible to do something like this??
}