I'm working with some legacy code and I need a StoreStrings class storing
some strings and able to return a MyString*.
I've tried with this:
typedef char MyString[64];
class StoreStrings{
public:
void store(MyString *aStr)
{
theVec.push_back(aStr);
}
const MyString* get(){return theVec.begin();}
private:
std::vector<MyString> theVec;
};
But I'm disappointed since it doesn't compile with this syntax.
StoreStrings myStore;
myStore.store("Hello");//cannot convert parameter 1 from 'char [6]' to 'char (*)[64]'
I've to instantiate one MyString before.
MyString myStr = "Hello";
myStore.store(&myStr);
How can I rewrite the StoreStrings class so to have myStore.store("Hello"); compiling?
Arrays cannot be used in STL containers as it requires the type to be copy constructible and assignable
You may try following, however std::string approach is best.
typedef char MyString[64];
struct X{
MyString s;
};
class StoreStrings{
public:
void store(MyString aStr)
{
X temp ;
for(int i=0;aStr[i];++i)
temp.s[i] =*(aStr+i);
theVec.push_back(temp);
}
// Here iterator is returned.
const std::vector<X>::iterator get(){return theVec.begin();}
private:
std::vector<X> theVec;
};
int main(){
StoreStrings myStore;
MyString m ="Hello";
myStore.store(m);
}
I would suggest something like that
Storestring.h
#pragma once
#include <vector>
class StoreStrings
{
public:
void store(const char* aStr)
{
pszStr = new char[64];
strcpy_s(pszStr,64,aStr);
theVec.push_back(pszStr);
};
~StoreStrings(void){
for(std::vector<char*>::iterator it = theVec.begin();it!=theVec.end();++it){
delete *it;
}
};
std::vector<char*>::iterator getBegin(){return theVec.begin();};
std::vector<char*>::iterator getEnd(){return theVec.end();};
private:
char* pszStr;
std::vector<char*> theVec;
};
main.cpp
#include "StoreStrings.h"
#include <iostream>
int main(void){
StoreStrings s;
s.store("a");
s.store("b");
s.store("c");
for(std::vector<char*>::iterator it = s.getBegin();it!=s.getEnd();++it){
std::cout << *it<<std::endl;
}
return 0;
};
Related
In the following code I made a template class, Its initialized in main function and I'm trying to assign char* as you can see below but It isn't working. I think the issue is in assign operator function I defined in Proxy class but I can't figure it out
#include <iostream>
using namespace std;
template <class T>
class Vector {
public:
T *p;
Vector(int size) {
p = new T[size];
}
class Proxy {
Vector &a;
int i;
public:
Proxy(Vector &a, int i) : a(a), i(i) {
}
void operator=(const T x) {
a.p[i] = x;
}
};
Proxy operator[](int i) {
return Proxy(*this, i);
}
};
int main() {
Vector<char *> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
I'm getting following error;
I already tried setting parameter in assignment operator function to const, I also tried implicitly typecasting to T nothing has worked
Try this:
using namespace std;
template <class T>
class Vector {
public:
T* p;
int sz;
Vector(int size) {
p = new T[size];
sz = size;
}
template<class T>
class Proxy {
Vector<T>& v;
int i;
public:
Proxy(Vector<T>& vec, int index) :v(vec),i(index) { }
void operator= (const T val) { v.p[i] = val; }
};
Proxy<T> operator[](int index) { return Proxy<T>(*this, index); }
};
Your code will work with any basic type, (int, char, double) and pointers, but not, for example, with this:
int main() {
Vector<char*> sv1(2);
sv1[0] = "John";
sv1[1] = "Doe";
}
Firstly, the Vector points to a char*, not a string literal (const char*). You'd have to cast it using a C-style cast or a const_cast. Example:
int main() {
Vector<char*> sv1(2);
sv1[0] = const_cast<char*>("John"); //succeeds
sv1[1] = (char*)"Doe"; //succeeds
sv1[0] = "John"; //fails
sv1[1] = "Doe"; //fails
}
A string literal is always a const char* in C++.
You'll have same error writing code:
char * whatever = "something";
This code is absolutely wrong at least for string:
void operator=(const T x)
{
a.p[i] = x;
}
Step 1: allocate buffer;
Step 2: copy string to allocated buffer.
Your code is OK for primitives like char, int, etc. The following code should work:
int main() {
Vector<char> sv1(2);
sv1[0] = 'J';
sv1[1] = 'D';
}
So I'm using the STL priority_queue<> with pointers... I don't want to use value types because it will be incredibly wasteful to create a bunch of new objects just for use in the priority queue. So... I'm trying to do this:
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
private:
int m_val;
}
priority_queue<Int*> myQ;
myQ.push(new Int(5));
myQ.push(new Int(6));
myQ.push(new Int(3));
Now how can I write a comparison function to get those to be ordered correctly in the Q? Or, can someone suggest an alternate strategy? I really need the priority_queue interface and would like to not use copy constructors (because of massive amounts of data). Thanks
EDIT: Int is just a placeholder/example... I know I can just use int in C/C++ lol...
You can explicitly specify which comparator your queue should use.
#include <iostream>
#include <sstream>
#include <functional>
#include <vector>
#include <queue>
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
bool operator<(const Int &other) const { return m_val < other.m_val; }
private:
int m_val;
};
template<typename Type, typename Compare = std::less<Type> >
struct pless : public std::binary_function<Type *, Type *, bool> {
bool operator()(const Type *x, const Type *y) const
{ return Compare()(*x, *y); }
};
int main(int argc, char *argv[]) {
std::priority_queue<Int*, std::vector<Int*>, pless<Int> > myQ;
for (int i = 1; i < argc; i++) {
std::stringstream ss(argv[i]);
int x;
ss >> x;
myQ.push(new Int(x));
}
for (; !myQ.empty(); delete myQ.top(), myQ.pop())
std::cout << myQ.top()->getVal() << std::endl;
return 0;
}
One option that will surely work is to replace Int* with shared_ptr<Int> and then implement operator< for shared_ptr<Int>
bool operator<(const shared_ptr<Int> a, const shared_ptr<Int> b)
{
return a->getVal() < b->getVal();
}
An integer is the same size as a pointer on 32 bit systems. On 64 bit systems, a pointer will be twice as big. Therefore, it is simpler/faster/better to use regular integers.
I have a class which stores a pointer to a data chunk and the size of the data. It implements operations like 'head', 'tail',... but it is irrelevant from the question's point of view. I use this instead of std::vector where I do not want deep copying.
However I need to copy the data sometimes, so I have a member function 'duplicate' to do it.
struct ByteArray {
char* data;
int size;
ByteArray(char* data, int size) : data(data), size(size) {}
ByteArray duplicate() const {
char *duplicatedData = new char[size];
memcpy(duplicatedData, data, size);
return ByteArray(duplicatedData, size);
}
};
Now I have a derived class - extending the previous class, where I need a duplicate method too, which calls the base class' duplicate. I have managed to solve it by casting both objects to the base class, but I suspect that this is not the best solution. Am I missing a more obvious solution? Also is this class the right solution to the original problem (not having deep copy) or there is standard solution what I'm not aware of?
struct Foo : ByteArray
{
int bar;
... // more members
Foo(ByteArray &bytes, int bar) : ByteArray(bytes), bar(bar) {}
Foo duplicate() const {
Foo dup = *this;
static_cast<ByteArray&>(dup) = ByteArray::duplicate();
return dup;
}
};
If you changed your Foo constructor to take a ByteArray by const reference instead, duplicate() would be pretty straightforward:
Foo duplicate() const {
return Foo(ByteArray::duplicate(), bar);
}
As-is, you can still do it the same way, just need an extra line:
Foo duplicate() const {
ByteArray ba = ByteArray::duplicate();
return Foo(ba, bar);
}
How about something like this then...
#include <cstring>
#include <iostream>
using namespace std;
struct ByteArray {
char* data;
int size;
ByteArray(char* data, int size) : data(data), size(size) {}
void duplicate(ByteArray &toCopy) const {
cout<<"Byte array duplicate."<<endl;
char *data = new char[toCopy.size];
memcpy(data, toCopy.data, size);
}
};
struct Foo : ByteArray
{
int bar;
Foo(ByteArray &bytes, int bar) : ByteArray(bytes), bar(bar) {}
void duplicate(Foo &toCopy) const {
cout<<"Foo duplicate."<<endl;
ByteArray::duplicate(toCopy);
}
};
int main(){
char* str = "some data";
char* null = "";
ByteArray barr (str, 9);
ByteArray barr2 = barr;
barr2.duplicate(barr);
Foo farr (barr, 2);
Foo farr2 = farr;
farr2.duplicate(farr);
}
I got stuck with pointer to const QList of pointers to Foo. I pass pointer to myListOfFoo from Bar object to Qux. I use pointer to const to prevent making any changes outside Bar class. The problem is that I'm still able to modify ID_ executing setID in Qux::test().
#include <QtCore/QCoreApplication>
#include <QList>
#include <iostream>
using namespace std;
class Foo
{
private:
int ID_;
public:
Foo(){ID_ = -1; };
void setID(int ID) {ID_ = ID; };
int getID() const {return ID_; };
void setID(int ID) const {cout << "no change" << endl; };
};
class Bar
{
private:
QList<Foo*> *myListOfFoo_;
public:
Bar();
QList<Foo*> const * getMyListOfFoo() {return myListOfFoo_;};
};
Bar::Bar()
{
this->myListOfFoo_ = new QList<Foo*>;
this->myListOfFoo_->append(new Foo);
}
class Qux
{
private:
Bar *myBar_;
QList<Foo*> const* listOfFoo;
public:
Qux() {myBar_ = new Bar;};
void test();
};
void Qux::test()
{
this->listOfFoo = this->myBar_->getMyListOfFoo();
cout << this->listOfFoo->last()->getID() << endl;
this->listOfFoo->last()->setID(100); // **<---- MY PROBLEM**
cout << this->listOfFoo->last()->getID() << endl;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Qux myQux;
myQux.test();
return a.exec();
}
Result of above code is:
-1
100
and what I'm trying to achieve is:
-1
no change
-1
There is no such problem when I use QList<Foo> instead of QList<Foo*> but I need to use QList<Foo*> in my code.
Thanks for help.
should be:
QList<const Foo *>* listOfFoo;
You could use a QList<Foo const *> const * which means you are not allowed to modify the list or the content of the list. The problem is that there is no easy way to retrieve that list from a QList<Foo*>, so you need to add it in your Bar class.
If you really have to return pointer, cast it to QList containing pointers to constant elements:
QList<const Foo*> const* getMyListOfFoo()
{return reinterpret_cast<QList<const Foo*> *>(myListOfFoo_);};
In Qux listOfFoo should contain pointers to constant elements too:
QList<const Foo*> const* listOfFoo;
So I'm using the STL priority_queue<> with pointers... I don't want to use value types because it will be incredibly wasteful to create a bunch of new objects just for use in the priority queue. So... I'm trying to do this:
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
private:
int m_val;
}
priority_queue<Int*> myQ;
myQ.push(new Int(5));
myQ.push(new Int(6));
myQ.push(new Int(3));
Now how can I write a comparison function to get those to be ordered correctly in the Q? Or, can someone suggest an alternate strategy? I really need the priority_queue interface and would like to not use copy constructors (because of massive amounts of data). Thanks
EDIT: Int is just a placeholder/example... I know I can just use int in C/C++ lol...
You can explicitly specify which comparator your queue should use.
#include <iostream>
#include <sstream>
#include <functional>
#include <vector>
#include <queue>
class Int {
public:
Int(int val) : m_val(val) {}
int getVal() { return m_val; }
bool operator<(const Int &other) const { return m_val < other.m_val; }
private:
int m_val;
};
template<typename Type, typename Compare = std::less<Type> >
struct pless : public std::binary_function<Type *, Type *, bool> {
bool operator()(const Type *x, const Type *y) const
{ return Compare()(*x, *y); }
};
int main(int argc, char *argv[]) {
std::priority_queue<Int*, std::vector<Int*>, pless<Int> > myQ;
for (int i = 1; i < argc; i++) {
std::stringstream ss(argv[i]);
int x;
ss >> x;
myQ.push(new Int(x));
}
for (; !myQ.empty(); delete myQ.top(), myQ.pop())
std::cout << myQ.top()->getVal() << std::endl;
return 0;
}
One option that will surely work is to replace Int* with shared_ptr<Int> and then implement operator< for shared_ptr<Int>
bool operator<(const shared_ptr<Int> a, const shared_ptr<Int> b)
{
return a->getVal() < b->getVal();
}
An integer is the same size as a pointer on 32 bit systems. On 64 bit systems, a pointer will be twice as big. Therefore, it is simpler/faster/better to use regular integers.