How can I declare a member vector of the same class?
This paper was adopted into C++17 which allows incomplete types to be used in certain STL containers. Prior to that, it was Undefined Behavior. To quote from the paper:
Based on the discussion on the Issaquah meeting, we achieved the
consensus to proceed* with the approach – “Containers of Incomplete
Types”, but limit the scope tostd::vector
,std::list
, and
std::forward_list
, as the first step.
And as for the changes in the standard (emphasis mine):
An incomplete type
T
may be used when instantiatingvector
if the
allocator satisfies the allocator-completeness-requirements
(17.6.3.5.1). T shall be complete before any member of the resulting
specialization of vector is referenced.
So, there you have it, if you leave the default std::allocator<T>
in place when instantiating the std::vector<T, Allocator>
, then it will always work with an incomplete type T
according to the paper; otherwise, it depends on your Allocator being instantiable with an incomplete type T
.
A is an incomplete type, right? If there was a vector of A*s I would understand. But here I don't understand how it works. It seems to be a recursive definition.
There is no recursion there. In an extremely simplified form, it's similar to:
class A{
A* subAs;
};
Technically, apart from size
, capacity
and possibly allocator
, std::vector
only needs to hold a pointer to a dynamic array of A
it manages via its allocator. (And the size of a pointer is known at compile time.)
So, an implementation may look like this:
namespace std{
template<typename T, typename Allocator = std::allocator<T>>
class vector{
....
std::size_t m_capacity;
std::size_t m_size;
Allocator m_allocator;
T* m_data;
};
}
How to pass a vector from a member function to another in the same class?
you have two solutions you can declare your vector as a member variable
#pragma once
#include <string>
#include <iostream>
#include <vector>
class Game
{
std::vector<std::string> _l;
public:
Game();
~Game();
void draw();
};
or you can also just directly give as parameter to your function
but the member variable declaration seems to be the best solution
C++ how to declare a vector of objects as a member of a class
Item
must be defined before its usage as a template argument.
Technically, you may be able to get away with a forward declaration in specific contexts, but to save you time and frustration with learning the exact rules, it is easier to just make sure you have defined it first.
In general, the order of declarations are important. If you use a type in the declaration of another type, the used type must already be defined. Exceptions to this rule involve usage by pointer and reference which only require forward declaration.
Vector as a class member
You most certainly want to use std::vector<int> myVector
. No need to initialize it, as it gets automatically initialized in the constructor of your class and deallocated when your class is destroyed.
create a vector of instances of a class in c++
This:
vector <Student> ver[N];
Creates an array of N
elements. Each element is vector<Student>
. This is not you want. You were probably trying to create a vector of N
elements. The syntax for this is:
vector <Student> ver(N);
But you can't use this because your class does not have a default constructor. So your next alternative is to initializae all the objects with the same element.
vector <Student> ver(N, Student(0));
You also tried to create an array of students like this:
Student ver[N];
This will not work. Because it tries to initialize every element in the array with the default constructor. But your class does not have a default constructor. So this will not work. But this is why your original code did work:
Student ver_list[2] = {7, 9}; // Here you are using the constructor for your object.
// It uses the normal constructor you provided not the default one.
The other issues is that you can not run code outside a function(method).
So this will not work:
for(unsigned int i = 0; i < N; ++i )
ver[i].set_id(i);
In C++11 you can initialize a vector the same way as an array:
vector<Student> ver = { 0, 1, 2, 3, 4, 5};
If you don't have C++11 or initialization is more complex. Then you need to write a wrapper.
class VecWrapper
{
public:
std::vector<Student> ver;
VecWrapper()
{
ver.reserve(N);
for(unsigned int i = 0; i < N; ++i )
ver.push_back(Student(i));
}
};
Now You can place this in global scope and it will auto init.
VecWrapper myData; // myData.vec initializaed before main entered.
int main()
{}
Full solution:
Option 2:
#include<iostream>
#include<vector>
using namespace std;
const unsigned int N = 5;
// The following is not correct
// This creates an arrya of `N` elements each element is `vector <Student>`
//
// vector <Student> ver[N]; // Create vector with N elements
//
// The following lines are not allowed.
// All code has to be inside a function.
//
// for(unsigned int i = 0; i < N; ++i )
// ver[i].set_id(i);
// What you want is:
// I use the following because it is unclear if you have C++11 or not.
class VecWrapper
{
public:
std::vector<Student> vec;
VecWrapper()
{
vec.reserve(N);
for(unsigned int i = 0; i < N; ++i )
vec.push_back(Student(i));
}
};
VecWrapper myData; // myData.vec
int main()
{
cout<< "Hello, This is a code to learn classes"<< endl;
cout<< myData.vec[1].get_id() << endl;
return 0;
}
How to create a vector of class objects in C++?
vector<Site> myStack();
This is actually a function declaration. The function is called myStack
and it returns a vector<Site>
. What you actually want is:
vector<Site> myStack;
The type of neighbours
at the moment will store copies of the objects, not references. If you really want to store references, I recommend using a std::reference_wrapper
(rather than using pointers):
vector<reference_wrapper<Site>> neighbors;
declare a template vector member in a class without template the class?
There are a few different ways to shear this beast. It mostly depends on how you want to access this vector and how you determine its exact type at runtime.
std::variant
A variant can store a set of predetermined types. It's effective but also cumbersome if you have many different types because you have to funnel every access through some type checking.
class SomeClass {
public:
using variant_type = std::variant<
std::vector<int>, std::vector<double> >;
int _someField;
variant_type _fieldValues;
void print(std::ostream& stream) const
{
switch(_fieldValues.index()) {
case 0:
for(int i: std::get<0>(_fieldValues))
stream << i << ' ';
break;
case 1:
for(double i: std::get<1>(_fieldValues))
stream << i << ' ';
break;
default: break;
}
}
};
std::any
Any can hold literally any type. Improves extendability but makes working with the values hard.
class SomeClass {
public:
int _someField;
std::any _fieldValues;
void print(std::ostream& stream) const
{
if(_fieldValues.type() == typeid(std::vector<int>))
for(int i: std::any_cast<std::vector<int>>(_fieldValues))
stream << i << ' ';
else if(_fieldValues.type() == typeid(std::vector<double>))
for(double i: std::any_cast<std::vector<double>>(_fieldValues))
stream << i << ' ';
else
throw std::runtime_error("Not implemented");
}
};
Subclassing
The most elegant way (IMHO) is to use a templated subclass. Something like this:
class SomeClass {
public:
int _someField;
virtual ~SomeClass() = default;
virtual void print(std::ostream& stream) const = 0;
};
template<class T>
SomeClassT: public SomeClass
{
std::vector<T> _fieldValues;
public:
virtual void print(std::ostream& stream) const
{
for(const T& i: _fieldValues)
stream << i << ' ';
}
};
Or if you don't want to expose that part, make it a private member.
class SomeClassHelper {
public:
virtual ~SomeClassHelper() = default;
virtual void print(std::ostream& stream) const = 0;
};
template<class T>
SomeClassHelperT: public SomeClassHelper
{
std::vector<T> _fieldValues;
public:
virtual void print(std::ostream& stream) const
{
for(const T& i: _fieldValues)
stream << i << ' ';
}
};
class SomeClass {
public:
int _someField;
private:
std::unique_ptr<SomeClassHelper> helper;
public:
void print(std::ostream& stream) const
{ return helper->print(stream); }
};
Create vector of member variables from vector of class pointers
What you've got is the best you can do, if you need another vector. It can be made a bit more C++-like with std::transform
and an insert iterator, but it's hard to see how that code would be any clearer than your simple loop.
You cannot cast one vector type to another, even if their respective element types are related.
You can try to obviate the need for it by iterating over your existing container using filtering functions that stop you having to write ->member
everywhere, but that really depends on what you're trying to do (which we don't know).
Related Topics
Void Pointers: Difference Between C and C++
C++ Function to Count All the Words in a String
Which Headers in the C++ Standard Library Are Guaranteed to Include Another Header
What Is "Pch.H" and Why Is It Needed to Be Included as the First Header File
Cpp - Valgrind - Invalid Read of Size 8
What Happens to Uninitialized Variables? C++
Opencv Error: Assertion Failed (Size.Width>0 && Size.Height>0) Simple Code
Why Is My Helloworld Function Not Declared in This Scope
Convert a String to a Date in C++
Range Based For-Loop on Array Passed to Non-Main Function
Using Cmake with Multiple Compilers for the Same Language
Nonstatic Member as a Default Argument of a Nonstatic Member Function
Visual C++: #Include Files from Other Projects in the Same Solution