I am fairly new to C++ and this method just won't overload in Vector class.
class Vector {
...
void findTriDiagonalDeterminant(mpf_t *det, unsigned long long *d, double offset) {
...
}
void findTriDiagonalDeterminant(mpf_t *det, unsigned long long *d) {
findTriDiagonalDeterminant(det, d, 0);
}
}
class Matrix : public Vector {
private:
unsigned long long* dims;
public:
void findTriDiagonalDeterminant(mpf_t* det, int index) {
Vector::findTriDiagonalDeterminant(det, dims+index);
}
...
}
The g++ says
error: no matching function for call to ‘Matrix::findTriDiagonalDeterminant(__mpf_struct (*&)[1], long long unsigned int*)’
But there's a matching function: second one from the top in Vector class.
I tried the same without pointers (by substituting *d with d and dims+index by *(dims+index)) but it didn't help.
In C++ overloads in a child class hide the methods in the parent class, so only the function in Matrix can be called with a Matrix.
You can use using to expose the extra methods, something like this.
class Matrix : public Vector {
private:
unsigned long long* dims;
public:
using Vector::findTriDiagonalDeterminat;
void findTriDiagonalDeterminant(mpf_t* det, int index) {
Vector::findTriDiagonalDeterminant(det, dims+index);
}
...
}
I'm guessing (dims+index) is getting promoted to something else. Maybe try explicitly casting the result or assign the expression to an appropriate temporary variable.
Related
i am searching for a way to store different type of pointers in a map without using void* for obvious reasons. I actually know the types of the pointers at compile-time and these pointers as well as their types need to be const while their values need to be changed from times to times. The types are always some kind of numerical types.
Background:
The variables behind these pointer are actually always global variables which need to changed if an specific event happens. Eachs event has an Id, the first member of that map, which changes the variable to a value transported by that event as a string.
So far i think boost::variant would do the trick. I am new to variant and i dont know whether the following would work as expected regarding the constness, but i assume after reading the f*cking manual that it should be ok. The main issue still is how to change that value behind that pointer utilising the standard conversions:
class Data{
public:
typedef boost::shared_ptr<Data> Ptr;
typedef boost::variant<double*, float*, unsigned int*, int*, unsigned short*, short*, unsigned char*, char*> PodPointerVariant;
double factor;
const PodPointerVariant varPointer;
Data(PodPointerVariant variable) :
factor(0.0),
varPointer(variable) {}
}
std::map<unsigned int, Data::Ptr> dataMap;
unsigned int intValue;
float floatValue;
void main()
{
intValue = 1;
Data::Ptr newEntry(new Data(&intValue));
newEntry->factor = 1.1;
dataMap->insert(std::make_pair(1,newEntry));
// Omitted find key and safety if not found...
unsigned int eventId = 1;
*(dataMap[eventId]->varPointer) = 2.1 * dataMap[1]->factor; // Should be automagically converted to 2 because the pointer is of type unsigned int, but gives a compiler error? I cant dereference that normally.
}
Is there an easy way to dereference like this? Maybe using a visitor class? Or anything else? Ideally Data->varPointer shall only be initialised once and only the value may be changed, like a "double * const", so i gets checked at compiled-time if somebody messes around with that pointer.
Thank you!
UPDATE
After some trial and error i found out that it indeed works as expected. This is what i've done this far:
template<typename U>
struct DeRefAssignVisitor : public boost::static_visitor<>
{
U x;
double factor;
DeRefAssignVisitor(U x, double factor) : x(x), factor(factor) { }
template <typename T>
void operator()(T* const p) const
{
*p = (T)(x * factor);
}
};
class Data{
public:
typedef boost::shared_ptr<Data> Ptr;
typedef boost::variant<double * const, float* const, unsigned long* const, long* const, unsigned short* const, short* const, unsigned char* const, char* const, plcbit* const> PodReferenceVariant;
double factor;
const PodPointerVariant varPointer;
Data(PodPointerVariant variable) :
factor(0.0),
varPointer(variable) {}
template <typename T>
void setPointerValue(T value) { boost::apply_visitor(DeRefAssignVisitor<T>(value, this->factor), this->varPointer); }
}
std::map<unsigned int, Data::Ptr> dataMap;
unsigned int intValue;
float floatValue;
void main()
{
intValue = 1;
floatValue = 2.111;
Data::Ptr newEntry(new Data(&intValue));
newEntry->factor = 1.1;
dataMap->insert(std::make_pair(1,newEntry));
// Omitted find key and safety if not found...
unsigned int eventId = 1;
dataMap[eventId]->setPointerValue(floatValue); // Works like a charme: converting compatible types automagically :-)
}
Templates 4TW :-D Thanks everybody!
Actually you can use visitors from boost.
class AssignVisitor : public boost::static_visitor<>
{
public:
double x;
AssignVisitor(double x) : x(x) { }
void operator()(int* p)
{
*p = (int)x;
}
void operator()(double* p)
{
*p = (double)x;
}
//and so on
};
And then
boost::apply_visitor(AssignVisitor(2.1 * dataMap[1]->factor), dataMap[eventId]->varPointer);
i have a class
class Studentas
{
public:
static const int CPaz=10;
private:
string pavarde, vardas, grupe;
double paz[CPaz], // paþymiø masyvas
np; // paþymiø kiekis
double vidurkis;
double STsk;
public:
Studentas(): pavarde(""), vardas(""), grupe(""), np(0), STsk(1),vidurkis(0)
{ }
double imtinp(){return np;}
double imtipaz(int i){return paz[i];}
void Deti(string pav, string vard, string grup, int np, int pz[],double vid);
void grupeDETI(string grp,double vidurk){grupe=grp;vidurkis+=vidurk;}
double iv(){return vidurkis;} <---------------------------------------THE ONES IM USING
void isvestiVID(){vidurkis/=STsk;}
void pridetiSK(){STsk++;}
string ig(){return grupe;} <---------------------------------------THE ONES IM USING
string Spausdinti(int i);
string SpausdintiGrupes();
};
the bool i was using bool
myfunction(Studentas const &d1,Studentas const &d2){return (d1.iv() > d2.iv() || d1.iv()==d2.iv() && d1.ig() < d2.ig());}
vector<Studentas> grupe;(with whatever length)
sort(grupe.begin(), grupe.end(),myfunction);
and i get an error, " cannot convert 'this' pointer from 'const Studentas' to 'Studentas &' "
EDIT : i use void functions to get my variables.
EDIT2: thanks for all the help, i think i'll just bubble this one out.Dont have the time to waste, thanks again for the help.
EDIT3: dun goofed on my operator overlays, the method below works.
Mark your methods as const:
double iv() const {return vidurkis;}
This way you'll be able to call them on const objects, which is what d1 and d2 are.
All methods that logically don't need to modify the object should be marked const.
I've got a class with 3 private variables and one public method, that has 2 char parameter variables.
class InitLine
{
private:
char *a;
char b, c;
public:
InitLine(char *inita, char initc);
Init(char *a, char c);
};
Now the definition of the method is simple:
Initline::Init(char *a, char c)
{
for (b=0; b<c; b++)
*(a+c)=0;
}
Now my question is: If I wish to repeat the same actions with different parametertypes (*a and c, or one of them becomes an integer e.g.), is it necessary to create a new class, or can I use the existing one, doing some 'typecasting' or some other trick I don't know yet?
Thanks and regards
Uwe
Use templates, make the Init function a template of your arguments type.
template <typename T>
Init(char*a , T c){}
for instance
You have many places in your code, which should be fixed prior to any further operations.
Naming convention is terrible. What is a, b, c?
You use b as a loop indexer, while a local variable should be used there instead.
You don't show us, what is a. Where is it allocated? What is the size of memory pointed to by a?
I guess, that your code should look like the following:
class InitLine
{
private:
char * data;
int count;
public:
InitLine(char * newData, int newCount)
{
// Possible error checking?
data = newData;
count = newCount;
}
// No parameters needed here, I guess
void Init()
{
for (int i = 0; i < count; i++)
data[i] = 0;
}
};
As for your question, I'm not really sure, what you are trying to achieve and what do you want to know. If you want to write a generic class holding any type of arrays, you have to use templates:
template <typename T>
class InitLine
{
private:
T * data;
int count;
public:
InitLine(T * newData, int newCount)
{
// Possible error checking?
data = newData;
count = newCount;
}
// No parameters needed here, I guess
void Init()
{
for (int i = 0; i < count; i++)
data[i] = 0;
}
};
You have to use this class in the following way:
InitLine<char> line(myData, myDataSize);
// where myData is a char * and myDataSize is an int
If you want to write a few methods differing by their parameters, this technique is called method overloading and is available in C++:
void Init(char * a, int b) { /* sth */ }
void Init(int * a, int b) { /* sth */ }
Note, that compiler must be able to clearly distinguish, which method should be called. Eg.
void Test(int a) { }
void Test(char a) { }
Test(0); // Ambiguity: which method should be called?
These are only things coming to my mind, while reading your question. If it is not what you are asking for, consider editing the question to be more specific.
If you just want to have the whole class with different types (not just the Init), e.g. also have int *a; int b,c; then template classes are the other trick you don't know yet.
template <typename ANYTYPE> class InitLine
{
private:
ANYTYPE *a;
ANYTYPE b, c;
public:
void InitLine(ANYTYPE *inita, ANYTYPE initc);
void Init(ANYTYPE *a, ANYTYPE c);
};
template <typename ANYTYPE> void Initline<ANYTYPE>::Init(ANYTYPE *a, ANYTYPE c)
{
for (int b=0; b<c; b++)
*(a+c)=0;
}
... main()
{
Initline<int> iline; // initline class based on type int (ANYTYPE -> int)
int line[20];
Initline<char> cline; // initline class based on type char (ANYTYPE -> char)
char somechars[30];
iline.Init(line, 20);
cline.Init(somechars, 30);
I've read about solution const A a[3] = { {0,0}, {1,1}, {2,2} }, but in my program const can't be used:
class Paper: public PaperQueue{
...
protected:
typedef int (Utils::*funcPtr) (int, int); //I use external function there
funcPtr p;
Utils* fptr;
public:
int pricefunc(){
addprice = (fptr->*p) (t,price);
}
Paper(int n, unsigned int pr):PaperQueue(n){
...
p=&Utils::commonpricefunc;
}
void Put(int a){
...
}
...
}
class Bank{
...
void Buy(Paper &p){
(/*this function modifies many parameters in 'p'*/)
...
}
...
}
int main(){
Bank B;
int pn=5;
/* ? */ const Paper p[pn] = {{5,15},{5,15},{5,15},{5,15},{5,15}}; /* ? */
int paperloop=0;
...
p[paperloop].Put(p[paperloop].addprice);
B.Buy(p[paperloop]);
...
That gives me a LOT of errors(with pricefunc(),Put(),Buy(),...), or just "variable-sized object ‘p’ may not be initialized". Is there any way to make this array work? (Everything works fine if not to pass any parameters to constructor!)
You can't use initializer lists for classes (non-PODs) because that would bypass the call to the constructor. You'll have to change it to a POD or use std::vector in the following ways:
If the class is copyable, as it appears to be, you can create a std::vector and fill it with the values you want:
const vector<Paper> papers(5, Paper(5, 15));
If you want to initialize it with different values, you can use an initializer list, but this is only supported in C++11:
const vector<Paper> papers = {Paper(1, 1), Paper(2, 2)};
Without C++11, you'll have to add the elements one by one, but then you can't make the vector const:
vector<Paper> papers;
papers.push_back(Paper(1, 1));
papers.push_back(Paper(2, 2));
Please check the code below, it can be compiled:
class Paper {
public:
int x, y;
};
int main() {
Paper p[5] = {{5,15}, {5,15}, {5,15}, {5,15}, {5,15}};
}
Please refer this post for more details, I think it explains very well
I'm trying to compile class A, which has a member of class B, where class B has no default constructor and its only constructor requires multiple arguments. Simple, right? Apparently not...
Class A:
class SessionMediator
{
public:
SessionMediator()
: map_(16,100,100)
{}
Tilemap map_, background_, foreground_;
};
Class B:
struct Tile2D;
class Tilemap
{
public:
Tilemap(const unsigned int tile_size, const unsigned int width,
const unsigned int height)
: tiles_(NULL), tile_size_(tile_size)
{
Resize(width, height);
}
inline void Resize(const unsigned int width, const unsigned int height)
{ /* Allocate tiles & assign to width_, height_... */ }
unsigned int tile_size_, width_, height_;
Tile2D* tiles_;
};
I am instantiating SessionMediator like so:
int main(int argc, char** argv)
{
SessionMediator session;
return 0;
}
This is the error I am getting. I'm compiling in XCode on Mac OS 10.5.8 and the compiler is g++:
session_mediator.h: In constructor 'SessionMediator::SessionMediator()':
session_mediator.h:19: error: no matching function for call to 'Tilemap::Tilemap()'
tilemap.h:31: note: candidates are: Tilemap::Tilemap(unsigned int, unsigned int, unsigned int)
tilemap.h:26: note: Tilemap::Tilemap(const Tilemap&)
session_mediator.h:19: error: no matching function for call to 'Tilemap::Tilemap()'
tilemap.h:31: note: candidates are: Tilemap::Tilemap(unsigned int, unsigned int, unsigned int)
tilemap.h:26: note: Tilemap::Tilemap(const Tilemap&)
(Duplicate of above here)
Build failed (2 errors)
I wrote a short compilable example doing basically the same thing, to try to figure out what exactly I was doing wrong, which compiles just fine with no errors in g++:
class A
{
public:
A(int x, int y, int z)
: x_(x), y_(y), z_(z)
{}
int x_, y_, z_;
};
class B
{
public:
B()
: m_a(1,2,3)
{}
A m_a;
};
int main(int argc, char **argv)
{
B test;
return 0;
}
Why does it fail in the first example? The 3 arg constructor for Tilemap (in Ex#1) is being called in the same way that the 3 arg constructor for A is being called (in Ex#2).
The code seems pretty much identical to me in the two examples.
As I was trying to simplify my example a bit, I accidentally left out two important things: other data members in the SessionMediator class.
The problem was that I had two additional members of the Tilemap class ("background_" and "foreground_"), which weren't being initialized in the constructor initialization list like the first member "map_".
The constructor should be changed to this:
SessionMediator()
: map_(16,100,100), background_(1,1,1), foreground_(1,1,1)
{}
I apologize for any time wasted over this question; it turned out to be something much simpler. Hopefully someone else will see this question and realize the mistake they are making.
The only thing I can think of is if you are using the copy constructor:
SessionMediator a = b; or SessionMediator a (b);
You might get in the situation where the default copy constructor of SessionMediator would try to use the default constructor of Tilemap which will cause the error you have.
Try to put map_(16u,100u,100u) in the SessionMediator constructor call to make the constants unsigned. This is the only thing that comes to mind now :-).
This compiles fine for me:
class Tilemap
{
public:
Tilemap(const unsigned int tile_size, const unsigned int width,
const unsigned int height)
{
}
};
class SessionMediator
{
public:
SessionMediator(): map_(16u,100u,100u){}
Tilemap map_;
};
Well, when you do:
Tilemap map_;
You're calling the default ctor - but you don't have one defined, that's the error message.
On the extra:
Tilemap::Tilemap(const Tilemap&)
C++ generates a ctor that takes a reference for you. So the valid matches are (1) the one you defined which takes 3 args and (2) the auto-generated one that takes the const ref.