How to initialize variable dynamically in class declaration, and being not constant - c++

How to initialize variable(s) dynamically i.e. being not as constant, in class declaration which will be invoked/used without need of object instantiation such as a constructor for member function call immediately gets returned in a function ?
There must, side by side of that variable(s) in that class, be a constant member.
enum Value :int { NO,LOW,MED,HIGH };
template<Value V> class valuation {
public:
valuation(const ints) : pos(s) {};
valuation(int a, int b, int c) : j(a), k(b), l(c) {};
value() {
if (!V)
return (j+k+l) * pos;
}
private:
const int pos;
int j,k,l;
};
int a_function(int s) {
return valuation<NO>(s).value(); // no need object at all
}
int main() {
// somehow in run-time j, k, l has been given 1,2,3, or other valid values
int v = a_function(7) // e.g.
}
Thanks in advance

I think you want to declare your value method -- or at least a version of it -- as a static member. This will allow you to call the method without instantiating an object from your class.

Related

How to pass object array to a function?

class department
{
void max() ***HOW TO PASS ARRAY OF OBJECT HERE , WHAT PARAMETERS SHOULD I PASS***
{
}
};
class B : public department {
};
int main()
{
B a[10];
// a.max(a,n); ***HOW TO CALL THIS max FUNCTION***
return 0;
}
I want to pass the array of object a[10] to the max function. How do I call it and pass it?
I don't want to do it like this:
for(i = 0; i < n; i++)
{
a[i].max
}
You implemented max() as a non-static method of department, so you need a department object to call it on, like each B object in your array, eg:
for(int i = 0; i < 10; ++i)
{
a[i].max();
}
If this is not what you want, then max() needs to be taken out of department, or at least made to be static instead. Either way, you will have to change its input parameters to accept the array.
Try something more like this instead:
class department
{
public:
static void max(department *depts, int count)
{
//...
}
};
class B : public department {
};
int main()
{
B a[10];
department::max(a, 10);
return 0;
}
Online Demo
Alternatively:
class department {
};
class B : public department {
};
void max(department *depts, int count)
{
//...
}
int main()
{
B a[10];
max(a, 10);
return 0;
}
Online Demo
How to pass object array to a function?
The parameter of a function cannot be an array in C++. A parameter can be a reference to an array. Alternatively, it is common to pass iterator pointing to an element of an array. Object pointer is an iterator for an array.
department::max() is a non-static member function. It has empty parameter list, so it accepts no arguments at all, except for the implicit class instance that is used as the left hand operand of a member access operator. Since this function accepts no reference to array parameter nor a pointer parameter, there's no way to pass an array as an argument.
Here is an example of a function that does accept a reference to an array as a parameter, and of how to call such function:
void max(B (&arr)[10]);
int main()
{
B a[10];
max(a);
}

Is it possible to initialize a data member as const based on a bool passed in as argument in the constructor?

I have a class that takes in a boolean called fixed as an argument. I want it to initialize the data member position as const if fixed is true. Is this possible at all?
class PhysicsVertex
{
public:
PhysicsVertex(olc::vf2d position, const bool fixed = false) :
position(position), fixed(fixed)
{
}
olc::vf2d position; //make this const if fixed is true.
const bool fixed = false;
};
int main()
{
PhysicsVertex v1{ {0, 0}, true }; //initialize v1.position as const
PhysicsVertex v1{ {0, 0} }; //initialize v1.position as non-const
}
If your information about fixed parameter is needed at compile time then you can use templates
#include <type_traits>
struct vf2d
{
};
template <bool fixed>
class PhysicsVertex
{
public:
PhysicsVertex() :
position()
{
}
typename std::conditional<fixed, const vf2d, vf2d>::type position;
};
void foo()
{
auto vertex = PhysicsVertex<true>();
// vertex.position = vf2d(); - compile time error, you cannot change const member
auto vertex2 = PhysicsVertex<false>();
vertex2.position = vf2d(); // It works fine, you can change non const member
}
const class members are problematic, because they inhibit a whole bunch of compiler generated methods. For example PhysicsVertex cannot be copied. Often the better alternative is to not make it const but instead provide no means to modify it from outside the class:
class foo {
int x = 42;
public:
int get() { return x; }
};
The member is not modifyable.
Now to your quesiton. You cannot make it const or non-const based on a runtime value (at least not easily), but following the suggestion above you can conditionally allow to modify it or not:
class foo {
int x = 42;
bool modifyable = false;
public:
foo(bool modifyable) : modifyable(modifyable) {}
void set(int y) {
if (!modifyable) throw "cannot modify";
x = y;
}
};
You should reconsider whether you can already decide to make it const or non-const at compile time, because then you need not rely on runtime checks and excpetions but can use the approach described in this answer.

Accessing type members in C++

Given an container such as a vector<int>
#include <vector>
using namespace std;
vector<int> v{1, 2, 3};
Why does it seem to be quite difficult to access the public type members such as iterator and const_iterator? As I understand it, these names are part of the class (not the object) and must be accessed via :: to specify the scope, but is there a reason to forbid v.const_iterator when v is known?
Example:
int f(v.iterator it) {
return *it;
}
// or
int g(v::iterator it) {
return *it;
}
A workaround would be using decltype as in:
int h(decltype(v)::iterator it) {
return *it;
}
But this approach does not even work in classes, as the following fails:
class A
{
public:
int h(decltype(x)::iterator it) {
return *it;
}
private:
vector<int> x;
};
Edit
Just a little sidenote.
As pointed out, the meaning of v.iterator would depend on the type of v at the point of usage (compile time) ignoring runtime polymorphism. But the same is true for static class members.
Example:
struct A
{
static const int x = 1;
};
struct B : public A
{
static const int x = 2;
};
void eval()
{
B b;
A& ar = b;
b.x; // 2
ar.x; // 1, even though ar refers to the same underlying object (by the base type)
}
As #Slava pointed out in comments, decltype(x) is the way to do it:
#include <vector>
using namespace std;
vector<int> v{1, 2, 3};
int f(decltype(v)::iterator it) {
return *it;
}
int g(decltype(v)::iterator it) {
return *it;
}
class A
{
private:
vector<int> x;
public:
int h(decltype(x)::iterator it) {
return *it;
}
};
The member access . operator and scope resolution operator :: may not be overloaded. And as you might deduce from the names, . is used to access members, while :: is used to access scope.
#include <iostream>
struct B {
class iterator { };
// no need for typename, compiler knows that we mean typedef B::iterator, as he can only find it
iterator iterator1;
// member named the same as class, ops!
int iterator;
// we need to use typename here, B::iterator is resolved as member
// iterator iteartor3;
typename B::iterator iterator2;
};
int main() {
B bobj;
// we access the member iterator inside b
bobj.iterator = 1;
// we declare object of B::iterator type
// we need to tell compiler that we want only types
typename B::iterator iterator;
// this will work too
typename decltype(bobj)::iterator iterator2;
// we declare a member pointer to the iterator member inside some B class
// no typename, as I want pointer to member, not pointer to... type
int B::* pointer = &B::iterator;
// this is just a pointer to the iterator specifically in bobj class
int * pointer2 = &bobj.iterator;
// foo(bar)
bobj.*pointer = 1;
// this will work as expected
int decltype(bobj)::* pointer3 = &B::iterator;
}
Also, there are no "type members" in C++ (at least I couldn't find them in C++ standard). Classes and enumerations and typedefs declarations declared in a class as members are called "nested types" or "nested classes".
Basically, C++ lets you get either values or types when you access them through ::. So MyType::AnotherType is fine as well as MyType::AValue. When you go through an instance with ., it only means it want to resolve a symbol which is a kind of a value (field, func, etc.). Hope that helps.

Declare template without parameters

Is it possible to declare a template without parameters?
I have a template like:
template < int i, int j>
class X{
int doSomething() { return i+j;}
}
and now i want to use this Template in another class, but i don't know its parameter cause they are variable. But i would like to save different templates in a variable like this :
class Foo {
X var;
void setVar ( const X &newVar) { var = newVar; }
X getVar () { return var;}
}
Is there a way to save different types of the template in one variable ? or pointer ?
Thx for help
Templates are resolved at compile time; your template parameters can't depend on values that aren't known until runtime. Furthermore, each instance of a template is a different type: X<1, 2> and X<3, 4> are different just like two classes Foo and Bar are different; a variable of the one type can't hold a value of the other. You can't have a variable whose type is just X, because X is not a type (it's a template).
It doesn't make sense for a template to have no parameters; you don't need a template at all in that case. It's not clear why you're trying to use templates to add two variables. You probably want to just use a class that holds two integers passed to its constructor:
class X {
private:
int i, j;
public:
X(int i, int j): i(i), j(j) { }
int doSomething() const { return i + j; }
};
This will let you have variables of type X, and you can construct different instances of X with different values for i and j based on variables at runtime.
You would want to use type erasure. boost::any provides a good implementation which might suffice for your use case. Here's the example from there modified for your situation :
BOOST_TYPE_ERASURE_MEMBER((canDoSomething), doSomething, 0)
class Foo {
using X = any<canDoSomething<int(void)>>;
X var;
void setVar ( const X &newVar) { var = newVar; }
X getVar () { return var;}
int DoSomethingWithX() { return var.doSomething();}
}

C++ Array Member of Constant Length (Initialisation of)

I have a class that contains an array. I want this array to be set at the length of a constant:
// Entities.h
class Entities
{
private:
const int maxLimit;
int objects[maxLimit];
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
The main problem I'm having is with the constructor. I thought:
// Entities.cpp
Entities::Entities() : maxLimit(50)
{
currentUsage = 0;
cout << "Entities constructed with max of 50" << endl;
}
would have been sufficient...but not so. I don't know if I can use the initialiser list for array initialisation.
How can I initialise the objects array using the maxLimit const? I'm relatively new to classes in C++ but I have experience with Java. I'm mainly testing out this phenomenon of 'constness'.
The array must have a constant length. I mean a length that is the same for all objects of that class. That is because the compiler has to know the size of each object, and it must be the same for all objects of that particular class. So, the following would do it:
class Entities
{
private:
static const int maxLimit = 50;
int objects[maxLimit];
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
And in the cpp file:
const int Entities::maxLimit;
I prefer to use an enumeration for that, because i won't have to define the static in the cpp file then:
class Entities
{
private:
enum { maxLimit = 50 };
int objects[maxLimit];
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
If you want to have a per-object size of the array, then you can use a dynamic array. vector is such one:
class Entities
{
private:
const int maxLimit;
std::vector<int> objects;
int currentUsage;
public:
Entities();
bool addObject(int identifier);
void showStructure();
};
// Entities.cpp
Entities::Entities(int limit)
: maxLimit(limit), objects(limit), currentUsage(0)
{
cout << "Entities constructed with max of 50" << endl;
}
Best is to do as much initialization in the initialization list as possible.
You can use template argument if you need to set array size at compile time:
template<size_t maxLimit>
class Entities
{
int objects[maxLimit];
public:
Entities() {}
...
};
Entities<1000> inst;
to dynamically allocate the memory you may need to use the 'new' keyword like
objects would be defined like:
int * objects;
inside the constructor you would do:
objects = new int [maxLimit];
edit:
forgot to mention, you'll need to deallocate the array when you're done, probably in the destructor of the class.
delete[] objects;
const ints have to be initialized at declaration. If you don't know the value that it has to be at the time of declaration, you're going to have to adopt a different strategy.
You'll need to create the array in the constructor, while keeping a pointer outside. Is this what you want to do?
In your class :
private:
int maxLimit;
int* objects;
And outside:
Entities::Entities() : maxLimit(50)
{
currentUsage = 0;
cout << "Entities constructed with max of 50" << endl;
objects = new int[maxLimit];
}
Entities::~Entities()
{
delete [] objects;
}
If all objects have the same length, then length can be static. This makes it a constant integral expression allowed as an array bound:
class Entities
{
private:
static const int maxLimit = 50;
int objects[maxLimit];
int currentUsage;
//...
};
Remember that sizeof(Entities) is a valid expression. Each Entities object has that same size.
Use std::vector and you get the expected behaviour. No need to worry about pointers, copies, etc
#include <vector>
class Entities
{
private:
const int limit;
std::vector<int> objects;
public:
Entities(int a_limit)
: limit(a_limit), objects(a_limit)
{ }
void addObject(int identifier)
{
if (objects.size() == limit)
throw whatever;
objects.push_back(identifier);
}
};