I'm having trouble with the syntax for a homework program. The prompt is to overload an inserter in such a way that it can properly execute the program fragment:
for (int i = 0; i < v.size(); ++i)
cout << v[i] << endl;
cout << endl;
So, this is what I have so far, but I still get an error at the cout << v[i] statement (Invalid operands to binary expression):
unsigned int seed;
struct node
{
int integer;
double value;
};
double random(unsigned int &seed);
void initialize_vector(vector<node> &v);
template<typename T>
void print_vector(const vector<T> &v);
template<typename T>
ostream &operator <<(ostream &out, const vector<T> &v);
template<typename T>
void output(ostream &out, const vector<T> &v);
int main()
{
vector<node> v(10);
initialize_vector(v);
print_vector(v);
return 0;
}
double random(unsigned int &seed)
{
const int MODULUS = 15749;
const int MULTIPLIER = 69069;
const int INCREMENT = 1;
seed = ((MULTIPLIER * seed) + INCREMENT) % MODULUS;
return double(seed) / double(MODULUS);
}
void initialize_vector(vector<node> &v)
{
for (int i = 0; i < v.size(); ++i)
{
v[i].integer = int (11 * random(seed));
v[i].value = double (11 * random(seed));
}
}
template<typename T>
void print_vector(const vector<T> &v)
{
for (int i = 0; i < v.size(); ++i)
cout << v[i] << endl;
cout << endl;
}
template<typename T>
ostream &operator <<(ostream &out, const vector<T> &v)
{
output(out, v);
return (out);
}
template<typename T>
void output(ostream &out, const vector<T> &v)
{
cout << v.integer;
cout << setprecision(2) << fixed << setw(6) << v.value;
}
I've tried passing node instead of T, along with passing with and without const references for the last 3 functions, so again I assume my syntax in the void output function is wrong somehow. Any help or points in the right direction would be greatly appreciated.
*Note: I can't change the ostream &operator function.
cout << v[i] << endl;
If v is a vector of node, then you need one more function to overload operator << for a node
ostream &operator <<(ostream &out, const node &n)
{
out << n.interger << " " << n.value;
return out;
}
Related
I have a Class called "Vector". It consists of two private fields: std::vector<double> coordinates and int len. Methoddim() returns len.
I am overloading operator << like that:
friend std::ostream& operator<<(std::ostream& os, Vector& vec )
{
std:: cout << "(";
for ( int i = 0; i < vec.dim(); i++ ) {
if ( i != vec.dim()-1){
os << vec[i] << ", ";
} else {
os << vec[i];
}
}
os << ')';
return os;
}
An operator + like that:
friend Vector operator +(Vector& first, Vector& second)
{
if(first.dim() != second.dim()){
throw std::length_error{"Vectors must be the same size"};
}else {
Vector localVec(first.dim()); // same as {0,0,0...,0} - first.dim() times
for (int i = 0; i < first.dim(); i++){
localVec[i] = first[i] + second[i];
}
return localVec;
}
}
And operator [] like that:
double& operator[](int index)
{
return this->coordinates[index];
}
And here's the problem:
Vector x{1,2,4};
Vector y{1,2,3};
Vector z = x + y;
std:: cout << z; // it works perfectly fine - (2, 4, 7)
std:: cout << x + y; // it gives me an error
could not match 'unique_ptr<type-parameter-0-2, type-parameter-0-3>' against 'Vector'
operator<<(basic_ostream<_CharT, _Traits>& __os, unique_ptr<_Yp, _Dp> const& __p)
It seems to me that this error is related to parameter Vector& vec , but I don't know whether it's right and what should I do to fix it. If anyone could give me a hint (or tell me what I should read more about) - I would be very grateful.
Here's full code:
class Vector
{
private:
std::vector <double> coordinates;
int len;
public:
Vector(): len{0}, coordinates{} {};
Vector(std::initializer_list <double> coordinates_): len{static_cast <int>( coordinates_.size())}, coordinates{coordinates_} {}
Vector(int len) : len{len} {
for(int i = 0; i < len; i++){
coordinates.push_back(0);
}
}
int dim() const
{
return this->len;
}
double& operator[](int index)
{
return this->coordinates[index];
}
friend std::ostream& operator<<(std::ostream& os, Vector& vec )
{
std:: cout << "(";
for ( int i = 0; i < vec.dim(); i++ ) {
if ( i != vec.dim()-1){
os << vec[i] << ", ";
} else {
os << vec[i];
}
}
os << ')';
return os;
}
friend Vector operator +(Vector& first, Vector& second)
{
if(first.dim() != second.dim()){
throw std::length_error{"Vectors must be the same size"};
}else {
Vector localVec(first.dim());
for (int i = 0; i < first.dim(); i++){
localVec[i] = first[i] + second[i];
}
return localVec;
}
}
};
friend std::ostream& operator<<(std::ostream& os, Vector& vec)
This signature doesn't accept rvalues, and this is why the error happens for your temporary result here:
std:: cout << x + y;
Change the second parameter into const Vector& vec or provide an overload with an r-value reference parameter.
friend std::ostream& operator<<(std::ostream& os, const Vector& vec);
A temporary cannot bind to a non-const reference argument. You are missing const in at least two places. Most importantly here:
friend std::ostream& operator<<(std::ostream& os, const Vector& vec )
// ^^
And there should a const overload of operator[]
I can not get the idea of how to create Array template class properly in C++.
The problem is solely out of learning purposes.
Let me provide the code first.
Array.h :
//Developed by Trofimov Yaroslav on 30.03.2018
#ifndef _ARRAY_H_TROFIMOV_
#define _ARRAY_H_TROFIMOV_
#include <string>
template<const size_t n, typename T>
class Array {
static unsigned __freeId, __quantity;
unsigned _id;
T** _array;
const size_t _n;
public:
typedef const bool (* const BooleanResultDelegate)(const T&);
class ArrayError {
const std::string _reason;
const size_t _index;
const size_t _maxIndex;
public:
ArrayError(const size_t index, const size_t maxIndex,const std::string& reason = "")
: _index(index), _maxIndex(maxIndex), _reason(reason) {}
std::string explanation(void) {
std::string res += "Index: " + std::to_string(_index) + "\n";
res += "Max index: " + std::to_string(_maxIndex) + "\n";
res += "Reason: " + _reason + "\n";
return res;
}
};
explicit Array<n, T>(T* arrayFiller = 0)
: _n(n), _array(new T*[n]), _id(++__freeId) {
if(arrayFiller != 0) {
for(size_t i(0); i < length(); ++i) {
_array[i] = new T(*arrayFiller);
}
} else {
for(size_t i(0); i < length(); ++i) {
_array[i] = arrayFiller;
}
}
reportIfDebug<n, T>(*this, "created");
++__quantity;
}
explicit Array<n, T>(const T& arrayFiller)
: _n(n), _array(new T*[n]), _id(++__freeId) {
for(size_t i(0); i < length(); ++i) {
_array[i] = new T(arrayFiller);
}
reportIfDebug<n, T>(*this, "created");
++__quantity;
}
Array<n, T>(const Array<n, T>& that)
: _n(n), _array(new T[n]), _id(++__freeId) {
for(size_t i(0); i < length(); ++i) {
(*this)[i] = new T[that[i]];
}
reportIfDebug<n, T>(*this, "created");
++__quantity;
}
~Array<n, T>(void) {
removeAll();
delete [] _array; _array = 0;
reportIfDebug<n, T>(*this, "deleted", false);
--__quantity;
}
T* operator[](const size_t i) {
if(i > length()) {
throw ArrayError(i, _n, "out of bounds exception");
}
return _array[i];
}
const T* operator[](const size_t i) const {
if(i > length()) {
throw ArrayError(i, _n, "out of bounds exception");
}
return _array[i];
}
const size_t length() const {
return _n;
}
const unsigned getID() const {
return _id;
}
void removeAll(BooleanResultDelegate removeCondition = 0) {
for(size_t i(0); i < length(); ++i) {
if(removeCondition == 0 || removeCondition(*_array[i])) {
delete [] _array[i]; _array[i] = 0;
}
}
}
};
template<const size_t n, typename T>
unsigned Array<n, T>::__freeId(0);
template<const size_t n, typename T>
unsigned Array<n, T>::__quantity(0);
template<const size_t n, typename T>
void reportIfDebug(
const Array<n, T>& instance,
const char* const message,
const bool showContent = true) {
#ifndef NDEBUG
std::cout << "========================================" << std::endl;
std::cout << typeid(instance).name() << ' '
<< message << ' '
<< "id: " << instance.getID() << std::endl;
if(showContent) {
std::cout << instance;
}
std::cout << "========================================" << std::endl;
#endif
}
template<const size_t n, typename T>
std::ostream& operator<<(std::ostream& os, const Array<n, T>& instance) {
for(size_t i(0); i < instance.length(); ++i) {
if(instance[i] == 0) {
os << "[" << i << "]: " << instance[i] << "\n";
} else {
os << "[" << i << "]: " << *instance[i] << "\n";
}
}
return os;
}
#endif
Main.cpp :
//Developed by Trofimov Yaroslav on 30.03.2018
#include <iostream>
#include "Array.h"
int main(void) {
const Array<5, int> a(7);
std::cout << *a[2] << std::endl;
return 0;
}
What is the main problem right now - is that the client of my Array class would have to use [indirection operator *] and [0 value pointer check] to use the objects from array.
I do not want the client to do that. But, if I use reference instead of pointer as a return type of operator[] I will not be able to return types which do not have copy constructor and I will return trash if nothing was put there before.
It seems like in Java and C# the problem is not fixed as well. The user is getting a reference to an object there and definitely should check for null being returned. And [indirection operator *] is called automatically there.
I am trying to understand how to overload the '<<' operator. So i wrote a simple test code that I report part of if here:
class Buffer {
vector<char> buffer;
...
ostream& operator<< (ostream& out, const vector<char>& v) {
out << "[";
size_t last = v.size() - 1;
for(size_t i = 0; i < v.size(); ++i) {
out << v[i];
if (i != last)
out << ", ";
}
out << "]";
return out;
}
...
};
The way I use the class in the main is the usual but I get the following error. Why?
main.cpp:22:10: error: overloaded 'operator<<' must be a binary operator (has 3 parameters)
ostream& operator<< (ostream& out, const vector<char>& v) {
^
It needs to be a binary operator: Since you're adding the operator as a class member, it'll always be called on a instance of that class, like this:
Buffer myBuffer;
const vector<char> myVector;
myBuffer << myVector;
You should see this as a function equivalent to:
myBuffer.DoOperator(myVector);
.. which takes only one argument, not two! So you should skip the first argument!
class Buffer {
vector<char> buffer;
...
friend
ostream& operator<< (ostream& out, const Buffer& b) {
const vector<char>& v=b.buffer;
out << "[";
size_t last = v.size() - 1;
for(size_t i = 0; i < v.size(); ++i) {
out << v[i];
if (i != last)
out << ", ";
}
out << "]";
return out;
}
...
};
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm doing a custom Vector class for education purposes and I can't get the operator+ right. It triggers a breakpoint just after returning a value, but I don't know why, maybe the destructor or constructor, I don't know.
The rare part is, that when I change the operator+ to return T instead of Vector<T>, and returning thiscpy._els[i] the program runs fine. That's why I thought that the issue might be coming from constructor/destructor.
Anyways, here is the relevant part of Vector.h:
#include <initializer_list>
#include <functional>
typedef size_t SIZE;
template <class T>
class Vector {
private:
SIZE _sz;
T *_els;
public:
typedef std::function<void(Vector*)> sorting_function;
static const void populateVector(Vector*, const SIZE&, typename Vector<T>::sorting_function, const bool& sameLength = false);
Vector(SIZE sz = 0) : _sz(sz), _els(nullptr) {}
Vector(SIZE, const T&);
Vector(std::initializer_list<T>);
Vector(const Vector&);
Vector(Vector&& vec) : _sz(vec._sz), _els(vec._els) { delete[] vec._els; }
~Vector() { delete[] _els; }
Vector& operator=(const Vector&);
Vector& operator=(Vector&&);
Vector& operator=(std::initializer_list<T>);
Vector operator+(const Vector&);
SIZE size() const { return _sz; }
T* elems() const { return _els; }
int *begin() { return &_els[0]; } // for (auto i : Vector) {}
int *end() { return &_els[_sz]; } //
};
And here my relevant part Vector.cpp:
#include <stdexcept>
#include "Vector.h"
template <class T>
Vector<T>::Vector(const Vector& vec) {
cout << "Vector initializer" << endl;
if (this != &vec) {
populateVector(this, vec._sz, [&](Vector<T>* obj) {
for (SIZE i = 0; i < vec._sz; i++)
obj->_els[i] = vec._els[i];
});
}
}
template <class T>
Vector<T>& Vector<T>::operator=(const Vector<T>& vec)
{
cout << "Operator = const" << endl;
populateVector(this, vec._sz, [&](Vector<T>* obj) {
for (SIZE i = 0; i < vec._sz; i++)
obj->_els[i] = vec._els[i];
}, true);
return *this;
}
template <class T>
Vector<T>& Vector<T>::operator=(Vector<T>&& vec)
{
cout << "Operator = move" << endl;
populateVector(this, vec._sz, [&](Vector<T>* obj) {
for (SIZE i = 0; i < vec._sz; i++)
obj->_els[i] = vec._els[i];
});
delete[] vec._els;
return *this;
}
template <class T>
Vector<T>& Vector<T>::operator=(std::initializer_list<T> list)
{
populateVector(this, list.size(), [&](Vector<T>* obj) {
SIZE i = 0;
for (T elem : list)
obj->_els[i++] = elem;
});
return *this;
}
template <class T>
Vector<T> Vector<T>::operator+(const Vector<T>& vec)
{
cout << "Operator + const" << endl;
Vector<T> thiscpy(*this);
if (_sz != vec._sz) throw std::runtime_error("Vector size mismatch");
for (SIZE i = 0; i < _sz; i++)
thiscpy._els[i] += vec._els[i];
return thiscpy;
}
template <class T>
const void Vector<T>::populateVector(Vector<T>* obj, const SIZE& newsize, typename Vector<T>::sorting_function repopf, const bool& sameLength = false)
{
cout << "Pupulate vector" << endl;
if (sameLength && (obj->_sz != newsize)) throw std::runtime_error("Incompatible vector length");
obj->_sz = newsize;
try
{
if (obj->_els != nullptr) delete[] obj->_els;
obj->_els = new T[newsize];
repopf(obj);
}
catch (const std::exception& e)
{
obj->_sz = 0;
obj->_els = nullptr;
throw std::runtime_error("Couldn't populate vector");
}
}
And main.cpp:
int main() {
Vector<int> v1{ 1,2,3,4 }; //Vector<T>::Vector(std::initializer_list<T>);
Vector<int> v2{ 2,4,8,16 }; //Vector<T>::Vector(std::initializer_list<T>);
try
{
cout << "----------" << endl;
v1 + v2; //Triggers breakpoint
cout << "----------" << endl;
cout << "done" << endl;
}
catch (const std::exception& e)
{
cout << e.what() << endl;
}
cin.get();
return 0;
}
And the output of the program:
Pupulate vector
Pupulate vector
----------
Operator + const
Vector initializer
Pupulate vector
Your copy constructor never initializes els prior to calling populateVector, so it might not be nullptr (it also might be) and you're calling delete[] on whatever the content of the member pointer is. This can lead to undefined behavior.
If I have this code
struct Unit{
int coef; //coefficient
int exp; //exponent
};
class Func: private std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, Func);
};
How do I print it out?
I tried using the concept from here: http://www.cplusplus.com/forum/beginner/5074/
But without success:
ostream& operator<<(ostream &output, Func &pol)
{
list<Unit>::iterator i;
for( i = pol.begin(); i != pol.end(); ++i)
{
Unit test = *i;
output << test.coef << " ";
}
return output;
}
And do I initialize it correctly?
Func::Func()
{
Unit test;
test.coef = 0;
test.exp = 0;
Func::push_back(test);
}
Sorry. New to this about inheritance. Though it wasn't hard when it was about the classes I made myself.
Updated code:
struct Unit{
int coef; //coefficient
int exp; //exponent
Unit():coef(0),exp(0){}
};
class Func : public std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, const Func &);
};
Func::Func()
{
Unit test;
Func::push_back(test);
}
ostream& operator <<(std::ostream &output, const Func& pol)
{
for (list<Unit>::const_iterator i = pol.begin(); i != pol.end(); output << i->coef << " " << i->exp << " ", ++i);
return output;
}
It is not clear for me what do you want to do. Is is a requirement that you inherit from an STL list? I wouldn't do it.
But this at least would be a solution.
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator<<(std::ostream &os, Unit const& v)
{
os << v.coef << " " << v.exp << std::endl;
return os;
}
int main()
{
std::list<Unit> myList;
Unit element;
element.coef = 0;
element.exp = 0;
myList.push_back(element);
std::ostringstream os;
for (std::list<Unit>::const_iterator it = myList.begin(); it != myList.end(); ++it)
{
os << *it;
}
std::cout << os.str() << std::endl;
}
With C++11 this could be implemented much nicer, but I don't know what compiler you are using. I did not compile it so far, just hacked it down; so sorry for syntax errors.
First, regarding your printing. You can do it a number of ways, the most robust being defining free operators for each type. Such as:
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
The function is a little more complex. You would be better served to use the list as a member variable and provide an operator for stream insertion for that class. Such as:
#include <iostream>
#include <iterator>
#include <list>
#include <cstdlib>
struct Unit
{
int coef; //coefficient
int exp; //exponent
Unit(int coef, int exp=0)
: coef(coef), exp(exp)
{}
friend std::ostream& operator <<(std::ostream&, const Unit&);
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
class Func
{
public:
std::list<Unit> units;
friend std::ostream& operator <<(std::ostream&, const Func&);
};
std::ostream& operator <<(std::ostream& os, const Func& func)
{
std::copy(func.units.begin(), func.units.end(),
std::ostream_iterator<Unit>(os, " "));
return os;
}
int main()
{
Func func;
func.units.push_back(Unit(3, 2));
func.units.push_back(Unit(2, 1));
func.units.push_back(Unit(1, 0));
std::cout << func << endl;
return EXIT_SUCCESS;
}
Output
3X^2 2X^1 1X^0
Note: I did NOT properly hide members, provide accessors, etc. That I leave to you, but the general idea on how to provide output-stream operators should be obvious. You could significantly further enhance the output operator for a `Unit by:
Not printing exponents of 1
Only printing the coefficient for exponents of 0 (no X),
Not printing a 1 coefficient of any term with an exponent greater than 0
Not printing anything for terms with 0 coefficients.
These tasks I leave to you.