How to store different classes in a vector? - c++

I have two classes with different member type. I wanted to store these two different classes in a vector and then try to print out all values inside of that object. I written the following code:
#include <variant>
#include <string>
#include <vector>
#include <iostream>
class Box
{
public:
std::string m_name;
};
class Lox
{
public:
int m_number;
};
int main(int argc, char* argv[])
{
auto v = std::vector<std::variant<Box, Lox>>{"Milad", 30};
v.push_back(Lox{ 21 });
v.push_back(Box{ "ROme" });
assert(std::get<Lox>(v[0]).m_number == 21);
assert(std::get<Box>(v[1]).m_name == "ROme");
return 0;
}
These are my problems with MSVC compiler:
'variant': is not a member of 'std'
'variant': undeclared identifier
'Box': illegal use of this type as an expression

Related

lambda does not name a type in a class in C++ [duplicate]

This question already has answers here:
Why can't member initializers use parentheses?
(2 answers)
can not define and init a class member by Parentheses [duplicate]
(1 answer)
Closed last month.
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <queue>
auto cmp = [](int a, int b) {
return a > b;
};
class Test {
private:
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq(cmp);
};
int main(int argc, char const *argv[])
{
Test test;
return 0;
}
The output is below:
However, when I use the priority_queue in the main function, it can use the cmp.
Moreover, when I delete the 'cmp' in the 'pq'
auto cmp = [](int a, int b) {
return a > b;
};
class Test {
private:
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq;
};
int main(int argc, char const *argv[])
{
Test test;
return 0;
}
the complier told me:
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <queue>
auto cmp = [](int a, int b) {
return a > b;
};
int main(int argc, char const *argv[])
{
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq(cmp);
pq.push(1);
std::cout << pq.top() << std::endl;
return 0;
}
I do not know why? I know lambda is a anonymous class, but why in a class it cannot use, in the main function it can use?
Welcome to the wonderful world of the Most Vexing Parse (well, not really, but close enough).
class Test {
private:
std::priority_queue<int, std::vector<int>, decltype(cmp)> pq{cmp};
};
gcc 12 compiles this without any errors. Always use the uniform initialization syntax. It's your friend.

assignment operator error in unique pointer

I tried to use unique_ptr in c++ in a singelton pattern instead of raw pointer. when I want to assign a unique_ptr to another I got an error. I tried to use std::move to assign but it did not work. the code is as follow:
#include <iostream>
#include <memory>
#include <list>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
class ClientDB
{
private:
static unique_ptr<ClientDB> theDB;
ClientDB() {}
list<string> clients;
public:
~ClientDB() {}
static unique_ptr<ClientDB> getInstance()
{
if(theDB==nullptr)
theDB = make_unique<ClientDB>;
return theDB;
}
void addClient(string c) {clients.push_back(c);}
void printClients(ostream& os)
{
copy(clients.cbegin(),clients.cend(),ostream_iterator<string>{os,"\n"});
}
};
int main()
{
unique_ptr<ClientDB> db1{ClientDB::getInstance()};
db1->addClient("Mr. Schultz");
unique_ptr<ClientDB> db2{ClientDB::getInstance()};
db2->addClient("Mrs. James");
unique_ptr<ClientDB> db3{ClientDB::getInstance()};
db3->addClient("Mr. Karajan");
db1->printClients(cout);
}
and the error I got is
error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<ClientDB>’ and ‘<unresolved overloaded function type>’)
theDB = make_unique<ClientDB>;
and another question is if nullptr can be used for unique_ptr.
Finally by help of my teacher, I can solve the problem. there is some points should be considered.
1- for unique_ptr assignment, std::move:: should be used.
2- make_unique has no access to the private constructor, the constructor should be called explicitly:
theDB = unique_ptr<ClientDB>(new ClientDB());
3-The unique-ptr must be initialized outside the class:
unique_ptr<ClientDB> ClientDB::theDB;
4- Three unique pointers in main for the same object can not be used, only one is allowed for uniqueness. references to unique_ptr should be used instead:
unique_ptr<ClientDB>& db1=ClientDB::getInstance();
and finally the code should be like this
#include <iostream>
#include <memory>
#include <list>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
class ClientDB
{
private:
static unique_ptr<ClientDB> theDB;
ClientDB() {}
list<string> clients;
public:
~ClientDB() {}
static unique_ptr<ClientDB>& getInstance()
{
if(theDB==nullptr)
//theDB = move(make_unique<ClientDB>());
theDB = unique_ptr<ClientDB>(new ClientDB());
return theDB;
}
void addClient(string c) {clients.push_back(c);}
void printClients(ostream& os)
{
copy(clients.cbegin(),clients.cend(),ostream_iterator<string>{os,"\n"});
}
};
unique_ptr<ClientDB> ClientDB::theDB;
int main()
{
unique_ptr<ClientDB>& db1=ClientDB::getInstance();
db1->addClient("Mr. Schultz");
unique_ptr<ClientDB>& db2=ClientDB::getInstance();
db2->addClient("Mrs. James");
unique_ptr<ClientDB>& db3=ClientDB::getInstance();
db3->addClient("Mr. Karajan");
db1->printClients(cout);
}

how transfer function from template class

#include <iostream>
#include <windows.h>
#include <string.h>
#include <functional>
#include <stdint.h>
#include <stdio.h>
using namespace std;
template <typename T>
class someclass {
public:
T value;
int sum(int vl1, int vl2) { return vl1 + vl2; };
};
template <typename T>
class someclass2 {
public:
T value;
void print(const std::function<int(int, int)>& func) {
cout << func(3, 4) << '\n';
};
};
int main(int argc, const char **argv)
{
someclass<int> obj1;
someclass2<int> obj2;
obj2.print(obj1.sum);
}
Compiler show error on last line : error C3867: 'someclass::sum': non-standard syntax; use '&' to create a pointer to member
Note that
int sum(int vl1, int vl2) { return vl1 + vl2; };
doesn't use its owner class' member in any way, it safely can be declared static, in that case this code would work.
The problem with this code is that a member function got a different type from standalone function. It's a member of class someclass, so its type is int (someclass::*)(int, int) and to call it you need an instance of that class.
The literal solution in general case is to hide pass of this inside the functor created by lambda expression:
obj2.print( [&](int a, int b)-> int { return obj1.sum(a,b); } );
You can use std::bind to do that
int main(int argc, const char **argv)
{
someclass<int> obj1;
someclass2<int> obj2;
using namespace std::placeholders;
obj2.print(std::bind(&someclass<int>::sum, &obj1, _1, _2));
}

data structure for multigraphs

To make multigraphs which is weighted also , i do following thing
#include <iostream>
#include <vector>
using namespace std;
struct maps
{
vector<char> weight(10); //to store weight of self-loops and multi-edges
};
int main()
{
maps m1[101][101], m2[101][101];
return 0;
}
but I get following errors:
error: expected identifier before numeric constant
error: expected ‘,’ or ‘...’ before numeric constant
How can I fix this?
As Ade YU mentioned, do not define the size of your weight vector in it's declaration. Instead, do it in the initializer list in the constructor. This should do what you're looking for:
#include <iostream>
#include <vector>
using namespace std;
struct maps
{
maps() : weight(10) {}
vector<char> weight; //to store weight of self-loops and multi-edges
};
int main()
{
maps m1[101][101], m2[101][101];
return 0;
}
You need to initialize the vector in the constructor. Try this:
#include <iostream>
#include <vector>
using namespace std;
struct maps{
maps() : weight(10) {}
vector<char> weight;//to store weight of self-loops and multi-edges
};
int main()
{
maps m1[101][101], m2[101][101];
return 0;
}

How should I implement a static collection of Strings in my class

I am very new to C++ so this might be an easy question to answer. I am writing a class (Person) and when a Person is created it should be assigned a random name from a collection of predefined names. So within the Person class I would like to define some sort of static collection of strings that I can access randomly and therefore I would also need to know how many there are.
I am using Qt here too, so the solution should preferably be using things from the standard library or the Qt library.
I am from a Java background and in Java I would probably do something like:
private static final String[] NAMES = { "A", "B" };
What would be the equivalent in this case?
You could use QStringList.
Person.h:
class Person
{
private:
static QStringList names;
};
Person.cpp:
QStringList Person::names = QStringList() << "Arial" << "Helvetica"
<< "Times" << "Courier";
Assuming C++03:
class YourClass {
static const char*const names[];
static const size_t namesSize;
};
// in one of the translation units (*.cpp)
const char*const YourClass::names[] = {"A", "B"};
const size_t YourClass::namesSize = sizeof(YourClass::names) / sizeof(YourClass::names[0]);
Assuming C++0x:
class YourClass {
static const std::vector<const char*> names;
};
// in one of the translation units (*.cpp)
const vector<const char*> YourClass::names = {"A", "B"};
And of course you can use your favorite string type instead of const char*.
First, a very simple program for generating random names from a static array. The proper class implementation can be found further down.
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
// import the std namespace (to avoid having to use std:: everywhere)
using namespace std;
// create a constant array of strings
static string const names[] = { "James", "Morrison",
"Weatherby", "George", "Dupree" };
// determine the number of names in the array
static int const num_names = sizeof(names)/sizeof(names[0]);
// declare the getRandomName() function
string getRandomName();
// standard main function
int main (int argc, char * argv[])
{
// seed the random number generator
srand(time(0));
// pick a random name and print it
cout << getRandomName() << endl;
// return 0 (no error)
return 0;
}
// define the getRandomName() function
string getRandomName()
{
// pick a random name (% is the modulo operator)
return names[rand()%num_names];
}
Class implementation
Person.h
#ifndef PERSON_
#define PERSON_
#include <string>
class Person
{
private:
std::string p_name;
public:
Person();
std::string name();
};
#endif
Person.cpp
#include "Person.h"
#include <stdlib.h>
using namespace std;
static string const names[] = { "James", "Morrison",
"Weatherby", "George", "Dupree" };
static int const num_names = sizeof(names)/sizeof(names[0]);
Person::Person() : p_name(names[rand()%num_names]) { }
string Person::name() { return p_name; }
main.cpp
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "Person.h"
using namespace std;
int main (int argc, char * argv[])
{
// seed the random number generator
srand(time(0));
// create 3 Person instances
Person p1, p2, p3;
// print their names
cout << p1.name() << endl;
cout << p2.name() << endl;
cout << p3.name() << endl;
// return 0 (no error)
return 0;
}