need help on operator << overloading functions - c++

The error I'm getting right now is:
multiple definition of operator<<(std::ostream&, SingleSequence& s)
the error location is at one of the overload operator function:
std::ostream& operator<<(std::ostream& os, const SingleSequence& s)
{
os << s.name << " " << s.seq << " " << s.length << " " << s.gccontent << " " << s.type;
return os;
}
This is the driver part:
#include"Sequences.h"
#include <iostream>
#include <fstream>
#include <cmath>
#include <ctime>
#include <cstdlib>
using namespace std;
int main(){
cout << "Assignment #1" << endl;
Sequences mysequences;
cout << mysequences;
cout << "Sorted by name" << endl;
mysequences.sortByName();
cout << mysequences;
cout << "Sorted by length" << endl;
mysequences.sortByLength();
cout << mysequences;
cout << "... done!" << endl;
}
This is the Sequences.h
#ifndef SEQUENCES_H_
#define SEQUENCES_H_
#include<string.h>
#include<strings.h>
#include<string>
#include<iostream>
using namespace std;
enum sequenceType { dna, rna, protein };
struct SingleSequence{
std::string name;
std::string seq;
int length;
double gccontent;
sequenceType type;
};
class Sequences {
public:
Sequences();
virtual ~Sequences();
int getListSize() const{return datasize;}
const SingleSequence& get( int i) const{
if (i>=0 && i < datasize)
return data[i];
throw OUT_OF_BOUNDS;;//{ if (i>=0 && i < datasize)
}
// return data[i];
// throw OUT_OF_BOUNDS;} // C++ has exceptions - you can even throw ints;
void sortByName();
void sortByLength();
friend std::ostream& operator<<(std::ostream& os, const SingleSequence& s) ;
friend std::ostream& operator<<(std::ostream& os, const Sequences& seqs) ;
int datasize;
private:
/*
* Remember to keep all data members private
*/
static const int MAX_LIST_SIZE = 20;
SingleSequence data[MAX_LIST_SIZE];
static const int OUT_OF_BOUNDS = -1;
};
std::ostream& operator<<(std::ostream& os, const SingleSequence& s)
{ os << s.name << " " << s.seq << " "
<< s.length << " " << s.gccontent << " "<<s.type;
return os;
}
#endif /* SEQUENCES_H_ */
-------------------------------------------------------------
This is the main cpp file
#include "Sequences.h"
#include <iostream>
using namespace std;
Sequences::Sequences() {
data[0] = { "KCNH2 Primer Pair 1 Forward", "CCAACTGGTGGACCGTCATT", 20, 55.0, dna };
data[1] = { "KCNH2 Primer Pair 1 Reverse", "GACAGCCAGGTGAACATCCA", 20, 55.0, dna };
data[2] = { "KCNH2 Primer Pair 2 Forward", "TGGATGTTCACCTGGCTGTC", 20, 55.0, dna };
data[3] = { "KCNH2 Primer Pair 2 Reverse", "CCACGGAACCTCTGGCAATA", 20, 55.0, dna };
data[4] = { "KCNH2 Primer Pair 3 Forward", "GAACGGAAGTGTGCCAACTG", 20, 55.0, dna };
data[5] = { "KCNH2 Primer Pair 3 Reverse", "ACAGCCAGGTGAACATCCAG", 20, 55.0, dna };
data[6] = { "KCNH2 Primer Pair 4 Forward", "CTGGATGTTCACCTGGCTGT", 20, 55.0, dna };
data[7] = { "KCNH2 Primer Pair 4 Reverse", "ATTTCCACGGAACCTCTGGC", 20, 55.0, dna };
data[8] = { "KCNH2 Primer Pair 5 Forward", "TGAAAACCGCTCGTCTGC", 18, 55.6, dna };
data[9] = { "KCNH2 Primer Pair 5 Reverse", "GGTGGAGCATGTGTTGTT", 18, 50.0, dna };
datasize = 10;
}
void Sequences::sortByName(){
for(int i = 0; i < 10; i++){
//int flag = 1;
SingleSequence temp;
for(int j = 0; j < 9; j++){
if (data[j].name.compare(data[j+1].name) > 0){
temp = data[j+1];
data[j+1] = data[j];
data[j] = temp;
}
}
}
}
void Sequences::sortByLength(){
for(int a = 0; a < 10; a++){
SingleSequence temp1;
for(int b = 0; b < 9; b++){
if (data[b].length > data[b+1].length){
temp1 = data[b+1];
data[b+1] = data[b];
data[b] = temp1;
}
}
}
}
std::ostream& operator<<(std::ostream& os, const Sequences& seqs)
{os << " Sequences object " << endl;
for (int i=0; i < seqs.getListSize(); i++ )
os << " " << (i+1) <<": " << seqs.get( i ) << endl;
return os;
}

You have two definition of the same operator << function in .h and .cpp. Hence, multi-definition error.
Keep the declaration in .h. Makes sure it is outside of the class
std::ostream& operator<<(std::ostream& os, const SingleSequence& s);
std::ostream& operator<<(std::ostream& os, const Sequences& seqs);
And write the definition in you .cpp file
std::ostream& operator<<(std::ostream& os, const Sequences& seqs)
{
os << " Sequences object " << endl;
for (int i = 0; i < seqs.getListSize(); i++)
os << " " << (i + 1) << ": " << seqs.get(i) << endl;
return os;
}
std::ostream& operator<<(std::ostream& os, const SingleSequence& s)
{
os << s.name << " " << s.seq << " "
<< s.length << " " << s.gccontent << " " << s.type;
return os;
}

Related

Why is the 'info[]' of the struct records giving errors?

This program uses class and takes the info of employees from a file. I have mentioned the file below too. I have also mentioned the output i received even though there are error. There is something wrong in the output too but I think it is because of the info error that it's getting.
While running this program, I got this error message:
Error: Run-Time Check Failure #2 - Stack around the variable 'info' was corrupted.
There's also this message:
Unhandled exception at 0x00950A89 in employee.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
// The used file for this program is:
A.Smith 20001 25 40
T.Philip 20002 20 35
S.LOng 20003 15 50
G.Santos 20004 30 30
F.Farkas 20005 22 55
// The output after running even with the errors is:
This week's employee history
Name Id Rate Hours
* A.Smith 20001 $25/h 40h
* T.Philip 20002 $20/h 35h
* S.LOng 20003 $15/h 50h
* G.Santos 20004 $30/h 30h
* F.Farkas 20005 $22/h 55h
This week's payment
Name Payment
* ╠╠╠╠╠╠╠╠ $0 <----------There is this error too
* T.Philip $700
* S.LOng $825
* G.Santos $900
* A.Smith $1000
* The average wages of the employees: $685.00
// The code is:
/*
#include "pch.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include<iomanip>
*/
using namespace std;
struct records {
char name[50] = {};
char id[5] = {};
int rate = 0;
int hours = 0;
int pay = 0;
};
void take(records array[], const int a);
int calculator(records array[], const int a);
void swap(records array[], const int a);
double Average(records array[], int a);
ifstream infile;
int main()
{
const int n = 5;
This is the first time info is declared:
struct records info[n];
double averageWages;
int overTime = 0, i;
infile.open("Project 3.dat");
cout << "\n This week's employee history \n" << endl;
if (infile.is_open()) {
cout << " Name Id Rate Hours " << endl;
Here take function uses info of the struct:
take(info, n);
cout << endl << endl;
cout << "This week's payment\n" << endl;
cout << " Name Payment" << endl;
Also here other functions use info:
calculator(info, n);
swap(info, n);
for (i = 0; i < n; i++) {
cout << "*" << setw(10) << info[i].name << setw(10) << "$" << info[i].pay << endl;
}
averageWages = Average(info, n);
cout << "\n\n" << "* The average wages of the employees: $" << averageWages << endl << endl;
}
else {
cerr << "Error! file cannot open." << endl;
exit(1);
}
return 0;
}
// Taking records:
void take(records array[], const int a) {
for (int i = 0; i < a; i++) {
while (infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours) {
cout << "*" << setw(9) << array[i].name << setw(10) << array[i].id << setw(10) << "$" << array[i].rate << "/h" << setw(10) << array[i].hours << "h " << endl;
}
} infile.close();
}
//swap records to arrange it according to total payment received
void swap(records array[], const int a) {
bool tf; //true or false
do {
tf = false;
for (int i = 0; i < a; i++) {
if (array[i].pay > array[i + 1].pay) {
swap(array[i], array[i + 1]);
tf = true;
}
}
} while (tf);
records temp;
for (int i = 0; i < a - 1; ++i)
{
for (int j = i + 1; j < a; ++j)
{
if (array[i].pay > array[j].pay)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
To calculate average:
double Average(records array[], const int a) {
double total = 0;
double average;
for (int i = 0; i < a; i++) {
total = total + (array[i].pay);
average = total / a;
}
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
return (total / a);
}
// To calculate the salary:
int calculator(records array[], const int a) {
infile.open("Project 3.dat");
if (infile.is_open()) {
for (int i = 0; i < a; i++) {
infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours;
if (array[i].hours > 40) {
int overTime = (array[i].hours - 40)*1.5;
array[i].pay = ((array[i].rate) * 40) + (overTime*(array[i].rate));
}
else {
array[i].pay = (array[i].rate)*(array[i].hours);
}
}
for (int i = 0; i < a; i++) {
return (array[i].pay);
}
}
}
It's hard to find all potential problems with that fragmented code, but you'd be better off using std::strings instead of char[]. They are safer and also has a lot of built-in functions. They also work well with misc. functions in the STL.
Your struct records info[n]; will only hold n (5) elements. Use a standard container, like a std::vector instead in case you'd like to add more entries to the file.
Reading and writing to files can usually be done using custom stream operators and all the free functions you have to deal with a number of records could be collected in a class of its own. I've made one record struct and one Records class to demonstrate how they could be used Together.
#include <iostream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>
struct record {
std::string name{};
std::string id{};
int rate = 0;
int hours = 0;
int pay = 0;
// stream operators for reading/writing a record
friend std::istream& operator>>(std::istream&, record&);
friend std::ofstream& operator<<(std::ofstream&, const record&);
friend std::ostream& operator<<(std::ostream&, const record&);
};
// populate a record from an istream
std::istream& operator>>(std::istream& is, record& r) {
std::string line;
// get a line and check that it's > 30 chars long
if(std::getline(is, line) && line.size()>30) {
// extract the name and remove trailing spaces
r.name = line.substr(0, 30);
auto pos = r.name.find_last_not_of(' ');
if(pos != std::string::npos)
r.name = r.name.substr(0, pos+1);
// put the rest of the line in a stringstream
std::stringstream ss(line.substr(30));
// and extract the rest of the fields
if(ss >> r.id >> r.rate >> r.hours) {
// calculate pay
r.pay = r.rate * r.hours;
} else { // if extraction fails, set the stream in fail mode
is.setstate(std::ios_base::failbit);
}
} else is.setstate(std::ios_base::failbit);
return is;
}
// streaming a record to an ofstream (like a file)
std::ofstream& operator<<(std::ofstream& os, const record& r) {
os << std::setw(30) << std::left << r.name.substr(0, 30) << r.id << " " << r.rate << " " << r.hours << "\n";
return os;
}
// streaming a record to a generic ostream (like std::cout)
std::ostream& operator<<(std::ostream& os, const record& r) {
os << "* " << std::setw(30) << std::left << r.name << std::right << r.id
<< " $" << r.rate << "/h " << r.hours << "h $" << std::setw(4) << r.pay;
return os;
}
class Records { // a class to maintain a number of "record"s
std::vector<record> m_records{}; // stores all "record"s
public:
Records(const std::string& filename) {
record tmp;
std::ifstream e(filename); // open file
// and extract one record at a time and put it in m_records.
while(e>>tmp) m_records.emplace_back(std::move(tmp));
}
// sum on any member in "record"
template <typename field>
auto Sum(field f) const {
return std::accumulate(m_records.begin(), m_records.end(), 0,
[&](int a, const record& b) { return a + (b.*f); });
}
// average of any member in "record"
template <typename field>
auto Average(field f) const {
return static_cast<double>(Sum(f)) / m_records.size();
}
// sorting on any member in "record"
template <typename field, typename T>
void Sort(field f, const T& cmp) {
std::sort(m_records.begin(), m_records.end(),
[&](const record& a, const record& b){ return cmp(a.*f, b.*f); });
}
// return the number of "record" elements
std::vector<record>::size_type size() const { return m_records.size(); }
// access an element via subscript
record& operator[](std::vector<record>::size_type idx) { return m_records[idx]; }
const record& operator[](std::vector<record>::size_type idx) const { return m_records[idx]; }
// iterators to use in for-loops
std::vector<record>::const_iterator cbegin() const noexcept { return m_records.cbegin(); }
std::vector<record>::const_iterator cend() const noexcept { return m_records.cend(); }
std::vector<record>::const_iterator begin() const noexcept { return cbegin(); }
std::vector<record>::const_iterator end() const noexcept { return cend(); }
std::vector<record>::iterator begin() noexcept { return m_records.begin(); }
std::vector<record>::iterator end() noexcept { return m_records.end(); }
// stream operator to show all records
friend std::ostream& operator<<(std::ostream&, const Records&);
};
std::ostream& operator<<(std::ostream& os, const Records& R) {
os << " Name Id Rate Hrs Pay\n";
for(const auto& r : R) std::cout << r << "\n";
os << std::setprecision(2) << std::fixed;
os << "Average pay : $" << std::setw(7) << R.Average(&record::pay) << "\n";
os << " rate : $" << std::setw(7) << R.Average(&record::rate) << "\n";
os << " hours worked: " << std::setw(7) << R.Average(&record::hours) << "h\n";
return os;
}
int main() {
// create a "Records" entity called "info" by reading a file
Records info("Project 3.dat");
// misc sorting and showing the result
std::cout << "Sorted as read from the file:\n";
std::cout << info;
std::cout << "\nSorted according to name:\n";
info.Sort(&record::name, std::less<std::string>());
std::cout << info;
std::cout << "\nSorted according to id:\n";
info.Sort(&record::id, std::less<std::string>());
std::cout << info;
std::cout << "\nSorted according to pay:\n";
info.Sort(&record::pay, std::greater<int>());
// output example using iterators:
for(auto& rec : info) {
std::cout << rec << "\n";
}
std::cout << "\nSorted according to rate:\n";
info.Sort(&record::rate, std::greater<int>());
std::cout << info;
std::cout << "\nSorted according to hours:\n";
info.Sort(&record::hours, std::greater<int>());
std::cout << info;
// example using subscript, operator[]
if(info.size()>2) {
std::cout << "\ninfo[2] = " << info[2] << "\n";
}
}

std::setw for the whole operator<< of user-defined type

We know, that the std::setw() influence only on the next output.
So, what standard practice to align
the whole operator<< of user-defined type in table output:
class A
{
int i, j;
public:
friend ostream& opeartor<<(ostream& out, const A& a) {
return << "Data: [" << i << ", " << j << "]";
}
}
// ...
A[] as;
out << std::left;
for (unsigned i = 0; i < n; ++i)
out << std::setw(4) << i
<< std::setw(20) << as[i] // !!!
<< std::setw(20) << some_strings[i]
<< some_other_classes[i] << std::endl;
out << std::right;
Just add a setw() method to your class:
class A
{
int i, j;
mutable int width = -1;
public:
A& setw(int n) {
this->width = n;
return *this;
}
friend ostream& operator<<(ostream& out, const A& a);
};
And when you print it, if you want to align, simply use it:
int main() {
A as[5];
for (auto & a : as)
cout << a.setw(15) << endl;
}

Operator Overloading solution

i have made a c++ code. An MList that holds items in it. I overloaded the << operator to print the values in MList in a particular format. Here is the code:
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
string s = "";
s += "Size " + to_string(m.size_) + "\n";//out << m.size() << endl;
s += "Cap " + to_string(m.capacity_) + "\n"; //out << m.capacity() << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
s += m.ary[i].element + ",";//out << m.ary[i].element << ",";
else
s += m.ary[i].element;
}
//cout << "String : " << s;
return out << s;
}
But it does not print correct value. It prints the size and capacity right but not the values. Instead of values, it prints some signs like heart:
You can see it prints size and capacity right but not the values. Here is the relevant code. I am executing case 2 only right now:
#include<iostream>
using std::cout; using std::endl;
using std::ostream; using std::cin; using std::boolalpha;
#include<string>
using std::string;
using namespace std;
template <class V>
struct SetElement
{
V element;
int cnt;
SetElement() = default;
SetElement(V v) : element(v){}
};
template <class V>
ostream &operator<<(ostream & o,const SetElement<V> &p)
{
return o << p.element;
}
template <class V>
class MSet
{
private:
SetElement<V> *ary;
size_t capacity_;
size_t size_;
public:
MSet(V val)
{
capacity_ = 2;
ary = new SetElement<V>[capacity_];
ary[0].element = val;
ary[0].cnt = 1;
size_ = 1;
}
SetElement<V>* find(V val)
{
SetElement<V> *found = nullptr;
bool yes = false;
for (int i = 0; i < size_ && !yes; i++)
{
if (ary[i].element == val)
{
found = &ary[i];
yes = true;
}
}
return found;
}
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
string s = "";
s += "Size " + to_string(m.size_) + "\n";//out << m.size() << endl;
s += "Cap " + to_string(m.capacity_) + "\n"; //out << m.capacity() << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
s += m.ary[i].element + ",";//out << m.ary[i].element << ",";
else
s += m.ary[i].element;
}
//cout << "String : " << s;
return out << s;
}
};
int main(){
int test;
long l1, l2, l3;
cin >> test;
cout << boolalpha;
switch (test){
// ...
case 2: {
cin >> l1 >> l2;
MSet<long> m_l(l1);
auto p = m_l.find(l1);
if (p != nullptr)
cout << *p << endl;
else
cout << "Val:" << l1 << " not found " << endl;
p = m_l.find(l2);
if (p != nullptr)
cout << *p << endl;
else
cout << "Val:" << l2 << " not found " << endl;
//cout << "MList \n";
cout << m_l;
break;
}
// ...
}
}
You're adding the values into a temporary string, which may involve implicit conversions depending of the template type (here your numerical values were converted into characters).
Just print the values, without the temporary string:
friend ostream& operator<<(ostream &out, const MSet<V> &m)
{
out << "Size " << m.size_ << endl;
out << "Cap " << m.capacity_ << endl;
for (int i = 0; i < m.size_; i++)
{
if (i < m.size_ - 1)
out << m.ary[i].element << ",";
else
out << m.ary[i].element;
}
return out;
}

C++ Cycle through the addresses of an object

Objects (that are not dynamic) are blocks of data in memory.
Is there a way to cycle through and print each item in an object?
I tried doing it with 'this' but I keep getting errors.
#include "stdafx.h"
#include <iostream>
#include "TestProject.h"
using namespace std;
class myclass {
int someint = 10;
double somedouble = 80000;
int somearray[5] = {0, 1, 2, 3, 4};
public:
void somefunction();
};
void myclass::somefunction() {
cout << "\n test \n" << this;
myclass *somepointer;
somepointer = this;
somepointer += 1;
cout << "\n test2 \n" << *somepointer;
//Error: no opperator '<<' matches these operands
}
int main() {
myclass myobject;
myobject.somefunction();
return 0;
}
I'm guessing the error is because the types don't match. But I can't really figure a solution. Is there a dynamic type, or do I have to test the type somehow?
You must add friend global std::ostream operator << to display content of object
#include "stdafx.h"
#include <iostream>
using namespace std;
class myclass {
int someint;
double somedouble;
int somearray[5];
public:
myclass()
{
someint = 10;
somedouble = 80000;
somearray[0] = 0;
somearray[1] = 1;
somearray[2] = 2;
somearray[3] = 3;
somearray[4] = 4;
}
void somefunction();
friend std::ostream& operator << (std::ostream& lhs, const myclass& rhs);
};
std::ostream& operator << (std::ostream& lhs, const myclass& rhs)
{
lhs << "someint: " << rhs.someint << std::endl
<< "somedouble: " << rhs.somedouble << std::endl
<< "somearray: { ";
for (int iIndex = 0; iIndex < 5; iIndex++)
{
if (iIndex == 4)
lhs << rhs.somearray[iIndex] << " }" << std::endl;
else
lhs << rhs.somearray[iIndex] << ", ";
}
return lhs;
}
void myclass::somefunction() {
cout << "\n test \n" << this;
myclass *somepointer;
somepointer = this;
somepointer += 1; // wrong pointer to object with `object + sizeof(object)` address,
// data probably has been corrupted
cout << "\n test2 \n" << *somepointer; // displaying objects content
}
int main() {
myclass myobject;
myobject.somefunction();
return 0;
}
as you want to get to the object member using its pointers shifts I post another program
#include "stdafx.h"
#include <iostream>
using namespace std;
#pragma pack (push, 1) // force data alignment to 1 byte
class myclass {
int someint;
double somedouble;
int somearray[5];
public:
myclass()
{
someint = 10;
somedouble = 80000;
somearray[0] = 0;
somearray[1] = 1;
somearray[2] = 2;
somearray[3] = 3;
somearray[4] = 4;
}
void somefunction();
friend std::ostream& operator << (std::ostream& lhs, const myclass& rhs);
};
#pragma pack (pop) // restore data alignment
std::ostream& operator << (std::ostream& lhs, const myclass& rhs)
{
lhs << "someint: " << rhs.someint << std::endl
<< "somedouble: " << rhs.somedouble << std::endl
<< "somearray: { ";
for (int iIndex = 0; iIndex < 5; iIndex++)
{
if (iIndex == 4)
lhs << rhs.somearray[iIndex] << " }" << std::endl;
else
lhs << rhs.somearray[iIndex] << ", ";
}
return lhs;
}
void myclass::somefunction() {
int* pSomeInt = (int*)this; // get someint address
double *pSomeDouble = (double*)(pSomeInt + 1); // get somedouble address
int* pSomeArray = (int*)(pSomeDouble + 1); // get somearray address
std::cout << "someint: " << *pSomeInt << std::endl
<< "somedouble: " << *pSomeDouble << std::endl
<< "somearray: { ";
for (int iIndex = 0; iIndex < 5; iIndex++)
{
if (iIndex == 4)
std::cout << pSomeArray[iIndex] << " }" << std::endl;
else
std::cout << pSomeArray[iIndex] << ", ";
}
}
int main() {
myclass myobject;
myobject.somefunction();
return 0;
}
C++, by design, has no reflection feature. This means there is no generic, type-independent way to acces type metadata (e.g. the list of members if a class and their types) at runtime. So what you're trying to do (if I understand it correctly) cannot be done in C++.
Also I'm not sure what you meant by "objects (that are not dynamic)". all objects are blocks of data in memory, regardless of whether they are dynamically allocated or not.

Vector of any type from given struct

Is there any way to create a vector of any type of given structures?
struct STUDENCI
{
int indeks;
string imie;
string nazwisko;
};
struct PRZEDMIOTY
{
int id;
string nazwa;
int semestr;
};
struct SALE
{
string nazwa;
int rozmiar;
bool projektor;
double powierzchnia;
};
vector<ANY TYPE FROM STUDENCI, PRZEDMIOTY, SALE> TAB[3];
You can use a the variant library from boost (www.boost.org):
std::vector<boost::variant<STUDENCI, PRZEDMIOTY, SALE> > v;
E.g. Live on Coliru
#include <boost/variant.hpp>
#include <iostream>
#include <string>
#include <vector>
using std::string;
struct STUDENCI
{
int indeks;
string imie;
string nazwisko;
friend std::ostream& operator << (std::ostream& os, STUDENCI const& v) {
return os << "STUDENCI { " << v.indeks << ", " << v.imie << ", " << v.nazwisko << " }";
}
};
struct PRZEDMIOTY
{
int id;
string nazwa;
int semestr;
friend std::ostream& operator << (std::ostream& os, PRZEDMIOTY const& v) {
return os << "PRZEDMIOTY { " << v.id << ", " << v.nazwa << ", " << v.semestr << " }";
}
};
struct SALE
{
string nazwa;
int rozmiar;
bool projektor;
double powierzchnia;
friend std::ostream& operator << (std::ostream& os, SALE const& v) {
return os << "SALE { " << v.nazwa << ", " << v.rozmiar << ", "
<< std::boolalpha << v.projektor << ", " << v.powierzchnia << " }";
}
};
typedef std::vector<boost::variant<STUDENCI, PRZEDMIOTY, SALE> > Vector;
int main()
{
Vector v;
v.push_back(STUDENCI { 1, "imie", "nazwisko" });
v.push_back(PRZEDMIOTY { 1, "eng101", 3 });
v.push_back(SALE { "auditorium", 42, true, 250 });
for (auto& element: v)
std::cout << element << "\n";
}
Prints
STUDENCI { 1, imie, nazwisko }
PRZEDMIOTY { 1, eng101, 3 }
SALE { auditorium, 42, true, 250 }
That's what unions are for, see the reference for more information on the topic:
Union declaration