I have this small piece of code:
int add(int x, int y)
{
return x + y;
}
class A
{
public:
const static int (*FP)(int, int) = &add;
};
int main()
{
int x = 3;
int y = 2;
int z = A::FP(x, y);
return 0;
}
Under VS2012 this generates the following error:
error C2864: 'A::FP' : only static const integral data members can be initialized within a class.
Is there something I am not seeing? Or is it plainly not possible for some reason?
Christian
Initialize outside of the class definition, using a typedef to make the constness possible:
typedef int (*func_t)(int, int);
class A
{
public:
const static func_t FP;
};
const func_t A::FP = &add;
Without the typedef the declaration:
const static int (*FP)(int, int) = &add;
is a static function pointer named FP with a return type of const int, not a const function pointer. When compiled with warnling level /W4 the following diagnostic is emitted:
warning C4180: qualifier applied to function type has no meaning; ignored
this was not immediately apparent due to the ordering of the declaration, const static int instead of static const int.
In C++03. In class initialization of non-intgeral or enum data-types is not allowed.
class A
{
public:
typedef int (*FP_ptr)(int, int);
const static FP_ptr FP;
};
const A::FP_ptr
A::FP = &add;
C++11
class A
{
public:
constexpr static int (*FP)(int, int) = &add;
};
Thanks a lot, guys. I had pretty much the same problem recently. Just want to add the answer with "const" in the right place without declaring a new type:
class A
{
public:
static int (* const FP)(int, int);
};
int (* const A::FP)(int, int) = &add;
It is okay, to change the last line to(I am not sure if it is exactly the same thing, but it works):
int (* const A::FP)(int, int) = add;
The other way (how other people solve similar issue) would be something like:
class A
{
public:
static int FP(int, int);
};
int A::FP(int x, int y)
{
return add( &x, &y );
}
Related
I am going through a text book to freshen up my (fairly bad) C++ knowledge and I came across this code example (shortened):
class MyClass{
private:
int count;
double price;
string name;
public:
void setValues(const int&, const double&, const string&);
};
void MyClass::setValues(const int& c, const double& p, const string& n){
count = c;
price = p;
name= n;
}
int main(){
myClass pOne;
pOne.setValues(5, 0.75, "Kiwi");
return 0;
}
The Way I understand the const keyword and the way it was described in the book thus far is that I can use it to declare constants, which should not be subject to change. This is better for the compiler since it knows that the values won't change.
But here I use const every time I set values
void MyClass::setValues(const int& a, const double& p, const string& b)
once the values of pOne are set, I can change them over and over with the setValues function, so what is the point of making them const?
once the values of pOne are set, I can change them over and over with the setValues function, so what is the point of making them const?
This is flawed logic. Consider this small example:
const int x = 42;
int y = x;
The value of x is assigned to y. Just because x is constant does not imply that y is too. You can change the value of y afterwards.
In the function signature the const means the usual: You cannot modify the parameters. It would be odd if a setter would change them.
struct foo {
int value = 42;
void set(int& x) {
value = x;
x = 42; // what ?!?
}
};
int main() {
int a = 2;
foo f;
f.set(x);
std::cout << x; // prints 42.... what?!?
const int b = 3;
f.set(b); // error because b is const :(
}
The setter takes its parameters by constant references because it tries to avoid a copy (hence reference) and parameters are not modified by the call (hence const).
Passing int as const int& however, is not really recommended, because it isn't cheaper than passing the int by value.
When I try to call a function, passing in a reference to my variable which has the type int, to the function which takes a type of int, I get an error that seems to point out that the int is the type of the class it was declared in, why is this?
Header:
class MyClass {
public:
int MAJOR = 3;
int MINOR = 3;
int REV = 0;
}
Code:
glfwGetVersion(&MyClass::OPENGL_VERSION_MAJOR, &MyClass::OPENGL_VERSION_MINOR, &MyClass::OPENGL_VERSION_REV);
Error:
error: cannot convert 'int MyClass::*' to 'int*' for argument '1' to 'void glfwGetVersion(int*, int*, int*)'
Change to:
class MyClass {
public:
static const int MAJOR = 3;
static const int MINOR = 3;
static const int REV = 0;
};
If these versions are constant.
Otherwise as:
class MyClass {
public:
static int MAJOR;
static int MINOR;
static int REV;
};
Then somewhere in a .cpp file
int MyClass::MAJOR = 3;
int MyClass::MINOR = 3;
int MyClass::REV = 0;
Check live example here
&MyClass::OPENGL_VERSION_MAJOR is a pointer on member.
You may use
MyClass instance;
glfwGetVersion(&instance.OPENGL_VERSION_MAJOR,
&instance.OPENGL_VERSION_MINOR,
&instance.OPENGL_VERSION_REV);
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);
Hello guys i had this error while i was compiling
error:'unisgned int vehicle::accelerate' is not a static member of 'class vehicle'
Any idea how to fix this?
Header file
class vehicle
{
public:
enum Switch
{
SWITCH_ON=0,
SWITCH_OFF
};
vehicle();
~vehicle();
bool powerSwitch(Switch );
unsigned int accelerate(unsigned int );
unsigned int decelerate(unsigned int );
bool isMoving();
unsigned int getSpeed();
unsigned int setSpeed(unsigned int);
private:
unsigned int speed;
bool moving;
};
vehicle.cpp
unsigned int vehicle::accelerate(amount)
{
if(moving==true;){
speed+=amount;
}
return speed;
}
You are missing the type in the parameter list:
unsigned int vehicle::accelerate(unsigned int amount)
{
.....
}
As you have declared:
unsigned int accelerate(unsigned int );
So you must implement:
unsigned int vehicle::accelerate(unsigned int amount)
{
//...
The type needs to be given again at this point.
The error might be somewhere else, where you're trying to access the accelerate member not using the operator -> or ., but ::, apart from forgetting the type of the parameter
In C++, let's say that I have the following header file:
class Foo {
static int func0 (int, int);
static int func1 (int, int);
static int func2 (int, int);
static int func3 (int, int);
};
Is there anyway to do this via typedefs?
I tried:
class Foo {
typedef int(*func)(int, int);
static func func1;
static func func2;
static func func3;
static func func4;
};
And then in a cpp file
int Foo::func1(int a, int b) { return a + b; }
but I get the error:
Redefinition of func1 as different kind of symbol
func1 has been declared as a function pointer, not as a function which you are trying to define it as.
Example use of a function pointer:
typedef int (*func_t)(int, int);
int func1(int a, int b) { return a + b; }
int func2(int a, int b) { return a * b; }
funct_t op = func1;
assert(9 == op(4, 5));
op = func2;
assert(20 == op(4, 5));
Having said that, I am unsure what your exact intention is.
You can't do what you want with typedefs, but if you really, really want to do this, you could use the preprocessor.
#define MAKE_MY_FUNC(funcname) static int funcname(int, int)
class Foo {
MAKE_MY_FUNC(func0);
MAKE_MY_FUNC(func1);
MAKE_MY_FUNC(func2);
MAKE_MY_FUNC(func3);
};
#undef MAKE_MY_FUNC // To make sure that you don't get preprocessor misery afterwards.