How to make one counter for different template specializations? - c++

#include<string>
#include<iostream>
using namespace std;
template<class T>
class Student_Grades
{
string name;
int NoExams;
T *grades_ptr;
static int counter;
public:
Student_Grades(string n, int no)
{
name=n;
NoExams=no;
grades_ptr=new T[no];
counter++;
}
void Print()
{
cout<<"Name: "<<name<<endl;
cout<<"NoExams: "<<NoExams<<endl;
for(int i=0; i<NoExams; i++)
{
cout<<"Grade "<<i+1<<": "<<grades_ptr[i]<<endl;
}
cout<<endl<<endl;
}
void set_grade(int index, T grade)
{
grades_ptr[index]=grade;
}
T get_grade(int index)
{
return grades_ptr[index];
}
int get_counter()
{
return counter;
}
~Student_Grades()
{
delete[] grades_ptr;
counter--;
}
};
This code will create a different counter for every template specialization.
How do I make the counter global, meaning it will be incremented each time I create an object? In the Main, I created 3 Student_Grades objects, one with int specialization. one with double and one with char. The counter gives me 1. How do I get it to give me 3?

You can use a base class the aim of which is to count the number of instances:
#include<cassert>
struct B {
B() { cnt++; }
virtual ~B() { cnt--; }
static int cnt;
};
int B::cnt = 0;
template<typename T>
struct D: B {
D(): B{} { }
};
int main() {
D<int> d1;
D<float> d2;
assert(B::cnt == 2);
}
This way, it doesn't depend on the type of the specialization.
A slightly more configurable solution would be this one:
#include<cassert>
struct C {
C() { cnt++; }
virtual ~C() { cnt--; }
static int cnt;
};
int C::cnt = 0;
template<typename T, class Counter = C>
struct D: Counter { };
int main() {
D<int> d1;
D<float> d2;
assert(C::cnt == 2);
}
This one if you don't want to rely on inheritance:
#include<cassert>
struct C {
C() { cnt++; }
~C() { cnt--; }
static int cnt;
};
int C::cnt = 0;
template<typename T, class Counter = C>
struct D { const Counter c; };
int main() {
D<int> d1;
D<float> d2;
assert(C::cnt == 2);
}
And so on...

Related

C structure object member name as parameter

How can I pass a structure name, object name, different member name(whose value to be verified) as a parameter to a function ?
struct st{
int a;
int b;
}
bool verify(____ st , ____ b){
if(obj.b == 5)return true;
return false;
}
int main(){
st obj;
// now that I know all the names of members of struct name
// HOW can I verify passing different member name as parameter
cout<<verify(__,__);
}
For an instance:
(example with error)
#include<iostream>
using namespace std;
struct st{
int a;
int b;
};
bool verify(st obj, st.a val){
if(obj.a==val)
return true;
}
int main()
{
cout<<"Hello World"<<endl;
st obj;
cout<<verify(obj,a);
//cout<<verify(obj,b);
return 0;
}
You can use a pointer to data member:
bool verify(const st &obj, int st::* field) {
return obj.*field == 5;
}
...
st obj;
std::cout << verify(obj, &st::a);
std::cout << verify(obj, &st::b);
But the syntax is confusing and just passing a reference to the data member to verify is easier:
bool verify(int field) {
return field == 5;
}
...
st obj;
std::cout << verify(obj.a);
std::cout << verify(obj.b);
Using a template:
#include <iostream>
struct st
{
int a;
int b;
};
struct st2
{
int c;
int d;
};
template<typename T>
bool verify(const T &obj, int T::* field)
{
return obj.*field == 5;
}
int main()
{
st obj = {5, 6};
st2 obj2 = {5, 6};
std::cout << verify(obj, &st::a) << "\n"; // 1, since obj.a is 5
std::cout << verify(obj2, &st2::d) << "\n"; // 0, since obj.d is not 5
return 0;
}

A vector for different classes

I have a class with a vector I'd like to fill with one of two types of class, selected by the user. Let's call my classes option1 and option2
What I'd like to do it something like
class storage_class
{
public:
storage_class(int sel, int n)
{
if(sel == 1)
for(int i = 0; i < n; i++)
my_store.push_back(std::make_unique<option1>());
else if(sel == 2)
for(int i = 0; i < n; i++)
my_store.push_back(std::make_unique<option2>());
}
private:
// Something like this but that actually works
std::vector<T> my_store;
};
Then I'd like to use it like this, or something similar, so there's no need to modify this usage dependent on the option chosen.
int main()
{
storage_class store(1);
int n_iterations = 4;
for(int i = 0; i < n_iterations; i++)
{
store.my_store[i]->create_data();
}
}
The classes option1 and option2 will be mathematical simulations that will be creating data and themselves store this data in a vector that are members of the class.
I want to store multiple instances of either option in a vector and then manipulate them from there. I can use C++17.
As you have c++17 in use, you can simply use a std::variant as type for the container which itself can keep all types you want to have.
Example:
class A { public: void Do() { std::cout << "A::Do" << std::endl; } };
class B { public: void Go() { std::cout << "B::Go" << std::endl; } };
template<class... Ts> struct funcs : Ts... { using Ts::operator()...; };
template<class... Ts> funcs(Ts...) -> funcs<Ts...>;
int main()
{
std::vector<std::variant<A,B>> vec;
vec.push_back(A{});
vec.push_back(B{});
for ( auto& el: vec)
{
std::visit( funcs{ [](A& a){ a.Do(); }, [](B& b) { b.Go(); } }, el);
}
}
Output:
A::Do
B::Go
The classes are fully independent and the methods can be simply called with std::visit and passing a callable object herein. I provide a simple funcs implementation, which simply collect all callable entities to simplify to interface the call to different methods of different unrelated classes here.
As std::variant is some kind of a tagged union, it needs the storage for the biggest type you have in use. If this wastes to much memory, you can store a pointer to the instance instead, maybe with std::unique_ptr or std::shared_ptr if you like some assistance for memory management ;)
Here is an example that tries to stay as close to your example as it can using a template parameter on class storage_class. See working version here. I've added only option1 and made the member my_store public as you access it in your main function.
#include <memory>
#include <vector>
#include <iostream>
struct option1{
void create_data(){ std::cout << "created\n"; }
};
template<typename T>
class storage_class
{
public:
storage_class(int n)
{
for(int i = 0; i < n; i++)
my_store.push_back(std::make_unique<T>());
}
std::vector<std::unique_ptr<T>> my_store;
};
int main()
{
storage_class<option1> store(4);
int n_iterations = 4;
for(int i = 0; i < n_iterations; i++)
{
store.my_store[i]->create_data();
}
}
another option would be to use std::variant. See workign version here.
#include <memory>
#include <vector>
#include <variant>
#include <iostream>
struct option1{
void create_data(){ std::cout << "created 1\n"; }
};
struct option2{
void create_data(){ std::cout << "created 2\n"; }
};
class storage_class
{
public:
using option = std::variant<std::unique_ptr<option1>,std::unique_ptr<option2>>;
storage_class(int sel, int n)
{
if(sel == 0)
for(int i = 0; i < n; i++)
my_store.push_back(option(std::make_unique<option1>()));
else if(sel == 1)
for(int i = 0; i < n; i++)
my_store.push_back(option(std::make_unique<option2>()));
}
std::vector<option> my_store;
};
int main()
{
storage_class store(1, 4);
int n_iterations = 4;
for(int i = 0; i < n_iterations; i++)
{
std::get<1>(store.my_store[i])->create_data();
}
}
Standard way is to make option1 and option2 derived classes from a base_class which seems consistent with your sample main(). Using a generic Factory class template, here is an example:
#include <functional>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <vector>
// Generic Factory class template
template<typename K,typename T,typename... Ts>
class Factory
{
using Map = std::unordered_map<K, std::function<std::unique_ptr<T>(Ts...)>>;
const Map mMap;
public:
Factory(Map&& map):mMap(std::move(map)) { }
std::unique_ptr<T> operator()(const K& key, Ts... args) const
{
const typename Map::const_iterator itr = mMap.find(key);
return itr == mMap.cend() ? nullptr : itr->second(std::forward<Ts>(args)...);
}
};
class base_class
{
public:
virtual void create_data() = 0;
};
class option1 : public base_class
{
public:
void create_data() override
{
std::cout << "I'm option1." << std::endl;
}
};
class option2 : public base_class
{
public:
void create_data() override
{
std::cout << "I'm option2." << std::endl;
}
};
class storage_class
{
using SimulationFactory = Factory<int,base_class>; // Optionally add constructor parameter types
const SimulationFactory simulation_factory; // This can be made static const.
public:
storage_class(int sel, int n)
: simulation_factory(
{ { 1, []() { return std::make_unique<option1>(); } }
, { 2, []() { return std::make_unique<option2>(); } }
})
{
for (int i = 0; i < n; i++)
my_store.push_back(simulation_factory(sel));
}
std::vector<std::unique_ptr<base_class>> my_store;
};
int main()
{
int n_iterations = 4;
storage_class store(1, n_iterations);
for(int i = 0; i < n_iterations; i++)
{
store.my_store[i]->create_data();
}
}
This compiled for me on linux using g++ -std=c++17 main.cc.
There are improvements that can be made to this code, but I copied your main() function in order to illustrate the basic idea(s). Hope that helps.
Edit 21 Sept 2018 - Example of how to pass parameters into constructors.
File: factory.h
#pragma once
#include <functional>
#include <memory>
#include <unordered_map>
// Generic Factory class template
template<typename K,typename T,typename... Ts>
class Factory
{
using Map = std::unordered_map<K, std::function<std::unique_ptr<T>(Ts...)>>;
const Map mMap;
public:
Factory(Map&& map):mMap(std::move(map)) { }
std::unique_ptr<T> operator()(const K& key, Ts... args) const
{
const typename Map::const_iterator itr = mMap.find(key);
return itr == mMap.cend() ? nullptr : itr->second(std::forward<Ts>(args)...);
}
};
File: main.cc
#include "factory.h"
#include <iostream>
#include <string>
#include <vector>
class base_class
{
public:
virtual void create_data() = 0;
};
class option1 : public base_class
{
const double mD;
public:
option1(double d)
: mD(d)
{ }
void create_data() override
{
std::cout << "I'm option1: mD("<<mD<<')' << std::endl;
}
};
class option2 : public base_class
{
const double mD;
public:
option2(double d)
: mD(d)
{ }
void create_data() override
{
std::cout << "I'm option2: mD("<<mD<<')' << std::endl;
}
};
class storage_class
{
using SimulationFactory = Factory<int,base_class,double>; // Optionally add constructor parameter types
const SimulationFactory simulation_factory; // This can be made static const.
public:
storage_class(int sel, int n)
: simulation_factory(
{ { 1, [](double d) { return std::make_unique<option1>(d); } }
, { 2, [](double d) { return std::make_unique<option2>(d); } }
})
{
for (int i = 0; i < n; i++)
my_store.push_back(simulation_factory(sel,static_cast<double>(i)));
}
std::vector<std::unique_ptr<base_class>> my_store;
};
int main()
{
int n_iterations = 4;
storage_class store1(1, n_iterations);
storage_class store2(2, n_iterations);
for(int i = 0; i < n_iterations; i++)
{
store1.my_store[i]->create_data();
store2.my_store[i]->create_data();
}
}
Output:
I'm option1: mD(0)
I'm option2: mD(0)
I'm option1: mD(1)
I'm option2: mD(1)
I'm option1: mD(2)
I'm option2: mD(2)
I'm option1: mD(3)
I'm option2: mD(3)

Policy based design - policy implementation has to access members of the host class

I think the best way to explain my question is with a piece of code:
class IncreasingMultiplier {
protected:
IncreasingMultiplier(int initialMultiplier = 0, int incrementation = 1)
int getMultiplier() {
mCurrentMultiplier += mIncrementation;
return mCurrentMultiplier - mIncrementation;
}
void setMultiplier(int multiplier) {
mCurrentMultiplier = multiplier;
}
void setIncrementation(int incrementation) {
mIncrementation = incrementation;
}
private:
int mCurrentMultiplier;
int mIncrementation;`
}
class ConstMultiplier {
protected:
int getMultiplier() const {
return 10;
}
}
class NumberLogger {
public:
void log() {
int currentNumber = getNumber(); // How can I call this method?
std::cout << "Current number is " << currentNumber << std::endl;
}
}
template<
class MultiplierPolicy,
class LoggingPolicy
>
class Host : public MultiplierPolicy, public LoggingPolicy {
public:
int getNumber() const {
return mNumber * getMultiplier();
}
private:
int mNumber;
}
Basically, one policy may need to access members defined in the host class, which are in turn dependent on other policies supplied to the host class.
Thanks!
The following code compiles with VS2013 (have not tried with GCC):
#include <iostream>
class IncreasingMultiplier {
protected:
IncreasingMultiplier(int initialMultiplier = 0, int incrementation = 1)
: mCurrentMultiplier(initialMultiplier)
, mIncrementation(incrementation)
{}
int getMultiplier() {
mCurrentMultiplier += mIncrementation;
return mCurrentMultiplier - mIncrementation;
}
void setMultiplier(int multiplier) {
mCurrentMultiplier = multiplier;
}
void setIncrementation(int incrementation) {
mIncrementation = incrementation;
}
private:
int mCurrentMultiplier;
int mIncrementation;
};
class ConstMultiplier {
protected:
int getMultiplier() const {
return 10;
}
};
// Template the logger policy
// Unfortunately - couldn't get host inheritance CRTP pattern
// compiling in Visual Studio 2013 :(
// https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
template < typename t_Host >
class NumberLogger /*: public t_Host*/ {
public:
void log() {
// This part of the CRTP pattern does work in Visual Studio 2013
int currentNumber = static_cast<t_Host*>(this)->getNumber(); // How can I call this method?
std::cout << "Current number is " << currentNumber << std::endl;
}
};
// Template based on a list of policies
template<
typename PoliciesList
>
class Host : public PoliciesList::MultiplierPolicy, public PoliciesList::LoggingPolicy {
public:
Host() : mNumber(1) {}
int getNumber() /*const*/ {
return mNumber * getMultiplier();
}
private:
int mNumber;
};
// Un-templated policies list
// Could create a macro to declare various policy combinations:
class ConcretePoliciesList_Const
{
public:
typedef Host<ConcretePoliciesList_Const> MyHost;
typedef ConstMultiplier MultiplierPolicy;
typedef NumberLogger<MyHost> LoggingPolicy;
};
class ConcretePoliciesList_Increasing
{
public:
typedef Host<ConcretePoliciesList_Increasing> MyHost;
typedef IncreasingMultiplier MultiplierPolicy;
typedef NumberLogger<MyHost> LoggingPolicy;
};
int main()
{
ConcretePoliciesList_Const::MyHost const_host;
ConcretePoliciesList_Increasing::MyHost increasing_host;
std::cout << "Const policy:" << std::endl;
const_host.log();
const_host.log();
const_host.log();
std::cout << "Increasing policy:" << std::endl;
increasing_host.log();
increasing_host.log();
increasing_host.log();
return 0;
}
The resulting output is:
Const policy:
Current number is 10
Current number is 10
Current number is 10
Increasing policy
Current number is 0
Current number is 1
Current number is 2

Working with a void pointer

Given the following scenario where my data might be of different type based on some condition.
class myClass {
public:
myclass() {
if (condition1) {
bool boolValue = false;
data = boolValue;
} else if (condition2) {
int intValue = 0;
data = intValue;
} else if (condition3) {
unsigned int unsignedIntValue = 0;
data = unsignedIntValue;
} else if (condition4) {
long longValue = 0;
data = longValue;
} else if (condition5) {
double doubleValue = 0.0;
data = doubleValue;
} else if (condition6) {
float floatValue = 0.0;
data = floatValue;
} else if (condition7) {
char *buffer = new char[10];
data = buffer;
}
}
void* getData() const { return data; }
private:
void *data;
}
As it happens the value that my void pointer points to is strictly within each statement. Therefore what is returned with getData() might not be valid. If I do get the data it is simply because the memory location where I point to is not yet written over.
The solution I have come up with is this:
class myClass {
public:
myclass() {
if (condition1) {
boolValue = false;
data = boolValue;
} else if (condition2) {
intValue = 0;
data = intValue;
} else if (condition3) {
unsignedIntValue = 0;
data = unsignedIntValue;
} else if (condition4) {
longValue = 0;
data = longValue;
} else if (condition5) {
doubleValue = 0.0;
data = doubleValue;
} else if (condition6) {
floatValue = 0.0;
data = floatValue;
} else if (condition7) {
buffer = new char[10];
data = buffer;
}
}
void* getData() const { return data; }
private:
void *data;
bool boolValue;
int intValue;
unsigned int unsignedIntValue;
long longValue;
double doubleValue;
float floatValue;
char *buffer;
}
I was thinking there must be a more elegant way to do this. Any suggestions?
You could use a union to save a few bits in memory, and then use pointer casting to get the value from the union:
#include<iostream>
using namespace std;
class myClass {
public:
myClass(char *str){
data.str = str;
}
myClass(double d){
data.d = d;
}
myClass(float f){
data.f = f;
}
void *getData() { return (void*)&data; }
private:
union {
double d;
float f;
char *str;
} data;
};
int main(){
myClass c(2.0);
cout << *(double*)c.getData() << endl;
myClass f(3.0f);
cout << *(float*)f.getData() << endl;
myClass s("test");
cout << *(char**)s.getData() << endl;
system("pause");
}
/* prints
2
3
test
*/
If you don't need to change the type of the data after you create an object, then you could use a template class:
template <typename T>
class myBaseClass {
public:
// Declare common functions here.
T getData()
{ return data; }
protected:
T data;
protected:
// Disallow constructing instances of this class outside the child classes.
myBaseClass(T val) : data(val) { }
};
template <typename T>
class myClass: public myBaseClass<T> {
public:
myClass() : myBaseClass<T>(0) { }
};
You then specialize for char*:
template <>
class myClass<char*>: public myBaseClass<char*> {
public:
myClass() : myBaseClass(new char[10]) { }
};
You then create instances like this:
myClass<int> a;
myClass<float> b;
myClass<char*> c;
// etc.
int i = a.getData();
float f = b.getData();
char* str = c.getData();

Unexplainable call to class constructor generates "matching function error"

When I call merge_sort I get a string of errors as such the most readable is:
no matching function call to dynamic_array<int>::dynamic_array()
Does having a base class instantiate a sub class cause that sub-class to re-instantiate the calling base class?
This was my first guess.
// Calling main function
#include "c_dynamic_array.cpp"
int main()
{
dynamic_array<int> d1(20);
d1.order();cout << d1 << endl;
d1.rorder();cout << d1 << endl;
d1.randorder();cout << d1 << endl;
d1.merge_sort();cout << d1 << endl; // This line starts a string of errors
}
// Dynamic Array Class and Merge Inner (merge sort) Class
#include "c_include.cpp"
/*
Dynamic Array
*/
using namespace std;
template <typename> class merge_inner;
template <class T> class dynamic_array
{
protected:
T* array;
public:
int size;
void rorder();
void order();
void randorder();
void print_operator(ostream&)const;
dynamic_array(int sizein)
{
size=sizein;
array=new T[size]();
}
void merge_sort()
{
merge_inner<T> M1;
}
};
template <class T> void dynamic_array<T>::print_operator(ostream &os=cout)const
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
template <class T> void dynamic_array<T>::randorder()
{
srand(time(NULL));
int *ap;
for(ap=array;ap!=array+size;++ap){*ap=rand()%size;}
}
template <class T> void dynamic_array<T>::order()
{
int *ap,i=0;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
++i;
}
}
template <class T> void dynamic_array<T>::rorder()
{
int *ap,i=size-1;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
--i;
}
}
template<class T> ostream& operator<<(ostream& stream, dynamic_array<T> const& data)
{
data.print_operator(stream);
return stream;
}
/*
Merge Sort
*/
template <class T> class merge_inner : public dynamic_array <T>
{
using dynamic_array<T>::array;
private:
const static int size;
T *scratch;
void flip_if_unordered(int &x, int &y)
{
if(array[x]>array[y])
{
int tmp=array[x];
array[x]=array[y];
array[y]=tmp;
}
}
void merge_algo(int &left, int &right_begin, int &right)
{
int iter,iter_left=left,iter_right=right_begin;
for(iter=left;iter<=right;++iter)
{
if( (iter_right>right) || ((iter_left < right_begin) && (array[iter_left]<=array[iter_right])))
{
scratch[iter]=array[iter_left];
++iter_left;
}
else
{
scratch[iter]=array[iter_right];
++iter_right;
}
}
for(iter=left;iter<=right;++iter){array[iter]=scratch[iter];}
}
void merge_recurse(int left,int right)
{
int left_end=(left+((right-left)/2));
int right_begin=left_end+1;
if(((left+1)==right)){flip_if_unordered(left,right);return;}
else if ((left==right)){return;}
else
{
merge_recurse(left,left_end);
merge_recurse(right_begin,right);
merge_algo(left,right_begin,right);
}
}
public:
merge_inner()
{
scratch = new T[size]();
if(scratch != NULL){merge_recurse(0, size);}
}
};
/*Quick Sort
void quick_sort()
{
quick_recurse(0,size);
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
*/
dynamic_array seems to be missing a default constructor, and since it has a custom constructor the compiler will not provide one. Add this to your class:
dynamic_array()
{
size = 0;
array = new T[0](); // or NULL, but note that new T[0] will be != NULL
}
Alternatively, provide a default sizein for your existing constructor so that it can be used as a default constructor as well:
dynamic_array(int sizein = 0)
Since your base class dynamic_array<T> doesn't have a default constructor, every derived class constructor must call some base constructor one way or another. Put the base initialization in the constructor initializer list. For example:
template <typename T>
class merge_inner : public dynamic_array<T>
{
public:
merge_inner() : dynamic_array<T>(0) { }
// ...
};