Push to vector while assignment to an array - c++

I need to push some elements into an existing vector as I assign them to an array.
I am able to initialize them and then further copy them, but I need to do both the operations at once.
Say there is a Base class TestBase and derived class TestOne, TestTwo, TestThree. I have initialized them based on the type using an enum as shown.
I do have an existing vector which I want to push these items into.
enum class Type : std::uint8_t {
TYPE_ONE,
TYPE_TWO,
TYPE_THREE
}; //enum class Type
struct _ds {
enum class Type type;
std::shared_ptr<TestBase> p_str;
};
std::vector<std::shared_ptr<TestBase>> vec_base_ptrs;
int main(int argc, char *argv[]) {
_ds a_ds[] = {{Type::TYPE_ONE,std::make_shared<TestOne>()},
{Type::TYPE_TWO,std::make_shared<TestTwo>()},
{Type::TYPE_THREE,std::make_shared<TestThree>()}};
}
Now is there a possibility, where I can do the following, where I can push the pointers into vector as well as have it in array at the same it. Is it possible.
_ds a_ds[] = {{Type::TYPE_ONE,{vec_base_ptrs.push_back(std::make_shared<TestOne>())}},
{Type::TYPE_TWO,{vec_base_ptrs.push_back(std::make_shared<TestTwo>())}},
{Type::TYPE_THREE,{vec_base_ptrs.push_back(std::make_shared<TestThree>())}}};
Please let me know how to do it.
Also suggest if there are any other data structures that can help in solve this problem, with a note that I need to fill the vectors with the shared_ptrs as I am getting it from third party library.

Related

How to initialize and use an array of another class in a class? (C++)

So I am new to C++ and in Java, it was easy to use arrays of other classes and I was wondering if there was a way to use arrays of other classes like this:
#include <iostream>
#include <array>
#include <string>
using namespace std;
class Message
{...}
class UserMessageFile
{
private:
Message[] messages;
}
int main(int argc, const char * argv[])
{
return 0;
}
Why can't I use an array of the Message class in my UserMessageFile class? Do I need to include the Message class inside of the UserMessageFile class before I can do this? How exactly do I achieve this?
You cannot specify an array with unknown size as a class member (in fact you can't specify one unless it comes with a static initializer, and you can't have those in a class definition).
What you are looking for is std::vector.
class UserMessageFile
{
private:
std::vector<Message> messages;
};
You should almost always be looking to use std:: types. So use a std::vector or a std::array. If you really need to use a c style array you must do this:
Messages messages[10]; // Your syntax must have the array
// braces at the end and you must specify
// an array length.
Here is a live example.
Other syntax errors include:
Classes must end with a semicoln (class a {};).
Dont use ... in your class, this isn't recognized.

C++ struct with template in vector

I'm making a text adventure game in C++. This is the struct for an object in that game (something the user can pick up and put in the inventory)
template <int N>
struct Object
{
static const int length = N;
string names[N];
string description;
};
Examples of objects:
Object<2> flower = { {"flower", "the flower"}, "A strange looking flower"};
Object<3> book = { { "the book", "book", "recipe book" }, "The world's finest cocktail recipes now all in one easy to use companion." };
The multiple names are synonyms for the command parser, so the user can input "pick up book" or "pick up recipe book", which in both cases picks up the object book.
Now I'd like to create a vector inventory to store all the elements in the inventory.
vector<Object> inventory;
Now, off course, this gives me a compiler error, because it expects something like this:
vector<Object<5>> inventory;
However, some objects have more names than others, is something like this possible and if so, how?
vector<Object<N>> inventory;
All your different Object<N> classes are different types with different sizes. You can't put them in a homogenous container.
You would need some base class or base interface, and store pointers in the vector, relying on virtual dispatch and polymorphism when you pull the elements out. This would make your container of Objects a heterogenous container.
Alternatively, and preferably, drop the template and store the names in a member container:
struct Object
{
set<string> names;
string description;
};
vector<Object> easy;
PS. I don't consider Object to be a good name for any class. CompuChip's suggestion of InventoryItem makes more sense.
A vector needs to know the size of the objects it contains, so obviously it cannot allow varying template instances inside (sizeof(Object<N+X>) > sizeof(Object<N>)).
Remove the templated array from the main Object struct, and replace it with a common vector or list or string objects instead, and your problem is solved.
Derive Object from BaseObject, and form a vector of smart pointers to BaseObject:
struct BaseObject
{
virtual ~BaseObject() = default;
};
template<int N>
struct Object : public BaseObject
{
static const int length = N;
string names[N];
string description;
};
typedef shared_ptr<BaseObject> Objptr;
vector<Objptr> Inventory(1006);

Sharing the same container between two different classes

Say for example I have the following two classes:
class ChessBoard
{
std::vector <ChessPiece> pieceList;
}
class ChessSquare
{
std::vector <ChessPiece> pieceList;
}
What I want to do is allow both classes to have access to the exact same ChessPiece vector, so that both of them have read/write access to the EXACT SAME ChessPiece data. So say for example when ChessSquare updates the pieceList vector, the corresponding pieceList vector in ChessBoard will get updated as well, and vice-versa. How would I go about implementing this?
Use a pointer. Give them each a copy of the same pointer to the vector.
If you give them each a std::shared_ptr you get the added benefit of reference counting and cleanup handled once neither of the classes are left using it.
Use pointer or reference to the pieceList.
Create object ChessPiece and send pointer of this object to ChessBoard and ChessSquare. I hope you access to ChessPiece only from one thread, instead you have to protect your ChessPiece using mutex or something like that.
Pointer is the obvious choice. BUT if you are feeling crazy and want to over-engineer your project you could encapsulate the vector within its own class and make that class a globally visible singleton
Use pointer maybe a good way, but i think you should achieve your point like this:
class ChessBase
{
static std::vector <ChessPiece> pieceList;
}
class ChessBoard : ChessBase
{
//to do what you want.
}
class ChessSquare : ChessBase
{
//to do what your want.
}
You can access the vector in each class as their member.
Seeing as a chessboard is composed of chess squares, I might suggest having the vector in the chessboard class and a reference to it in the chess square class, maybe like so:
typedef std::vector<ChessPiece> PIECES
class ChessBoard
{
public:
ChessBoard()
{
// NOTE! your app might have more squares than this:
m_pSquare = new ChessSquare( pieceList );
}
private:
PIECES pieceList;
ChessSquare* m_Square;
}
class ChessSquare
{
public:
ChessSquare( const PIECES& pieces )
: refPieceList(pieces)
{
}
private:
const PIECES& refPieceList;
}

dynamically allocating a vector

is it possible to dynamically allocate a vector without specifying its Type ?
im creating a container class which should support all the numeric types
it must creat a container vector which type will be specified later when the first number is pushed into it .
first of all is this code correct ?
private :
vector<int> stk ;
public :
template <typename Typ>
void push (Typ input)
{
vector<Typ> temp ;
stk = temp ;
}
second : i somehow need to dynamically allocate the "stk" vector without specifying the type .
If this is C++ code, then templates are specialized at compile time. You cannot delay the allocation of a vector -- or any other template class instance -- to runtime.
A workaround would be to customize your own numeric class hierarchy with base class, say CNumeric, and allocate a vector of CNumeric*. Then the vector can accommodate any numeric type in your own class hierarchy. But of course, this workaround can be very inefficient.
You haven't explained the problem correctly or you haven't understood what you really need.
If I understand correctly this is what you are looking for.
template<typename Typ>
class A {
private :
vector<Typ> stk ;
public :
void push (Typ input)
{
stk.push_back(input) ;
}
}
Usually you don't need to change the type of things at runtime (and you can't in C++). Typically you want to change the design of your program.
If you really want to do this, you could use a union type that can hold one of a different number of things like here:
union A {
int i;
float f;
double d;
};
and then store a vector of A.

Initialising a 2D vector with values at declaration

I'm currently working on a program which randomly generates items (e.g. weapons, armour etc.) and I want to make global constant vectors which hold all the names that could be given to the items. I want to have this 2D vector in a header file that's available to all my other classes (but not modifiable), so I need to initialise it at declaration.
I previously used the following:
static const std::string v[] =
{
"1.0", "1.1", "1.2", "null"
};
const std::vector<std::string> versions( v, v+sizeof( v)/sizeof( v[0]));
This worked for a 1D vector, however I want to use a 2D vector to store item names.
I have tried using the following however it means I don't have the member functions (such as size()):
static const std::string g_wn_a[] = { "Spear", "Lance", "Jouster" };
static const std::string g_wn_b[] = { "Sword", "Broadsword", "Sabre", "Katana" };
const std::string* g_weapon_names[] = { g_wn_a, g_wn_b };
I also don't want to use a class to store all the names because I feel it would be inefficient to have variables created to store all the names everytime I wanted to use them.
Does anyone know how I can solve my problem?
You could use a class with const static members. This way, your class would just behave like a namespace and you wouldn't have to create an instance of the name-holding class to use the names.
struct MyNames {
// const static things
const static string myweapon = "Katana"
};
string s = MyNames::myweapon; // s = "Katana"
This is C++, so the most common way to do this is to write a class that does this in its constructor, and then create a const object of that class. Your class would then provide various member functions to query the various items it maintains.
As a bonus, this will make it easier for the rest of your code to use the various items.