I would like to implement a Base class with attributes of a size I already know at compile-time. So my idea was to use a template for this Base class. The following code compiles and runs fine under VC++9.0.
Class definition in the .h file
template<int N> class BaseClass
{
int* idx;
int* incr;
int* limit;
public:
BaseClass(void);
~BaseClass(void);
void LoopMethod(void);
};
Implementation of the class methods in the .cpp file
#include "BaseClass.h"
#include<iostream>
using namespace std;
// instantiation
template class BaseClass<2>;
template<int N> BaseClass<N>::BaseClass(void)
{
idx = new int [N];
incr= new int [N];
limit = new int[N];
for(int m = 0; m < N; m++)
{
idx[m] = 0;
incr[m] = 1;
limit[m] = 2;
}
}
template<int N> BaseClass<N>::~BaseClass(void)
{
}
template<int N> void BaseClass<N>::LoopMethod( )
{
for( idx[N-1]; idx[N-1] < limit[N-1]; idx[N-1] += incr[N-1] )
{
cout << "LoopMethod Nr " << N-1 << " is called." << endl;
}
}
Implementation of the main-function:
#include<cstdlib>
#include "BaseClass.h"
using namespace std;
int main()
{
BaseClass<2> baseObj;
baseObj.LoopMethod();
system("PAUSE");
return 0;
}
Now I want to nest the for-loops from the LoopMethod times the size of the class attributes. I.e. the compiler should generate a code I would write by Hand as
template<int N> void BaseClass<N>::LoopMethod( )
{
for( idx[0]; idx[0] < limit[0]; idx[0] += incr[0] )
{
for( idx[1]; idx[1] < limit[1]; idx[1] += incr[1] )
{
cout << "LoopMethod Nr " << 1 << " is called." << endl;
}
cout << "LoopMethod Nr " << 0 << " is called." << endl;
}
}
Anyway, I can prompt the compiler to do this, if I do not declare the BaseClass to be a template class. The code for this would then look like:
class BaseClass
{
int* idx;
int* incr;
int* limit;
public:
BaseClass(void);
~BaseClass(void);
template<int M> void LoopMethod(void);
};
Implementation of the class methods in the .cpp file
#include "BaseClass.h"
#include<iostream>
using namespace std;
template void BaseClass::LoopMethod<1>();
BaseClass::BaseClass(void)
{
idx = new int [2];
incr= new int [2];
limit = new int[2];
for(int m = 0; m < 2; m++)
{
idx[m] = 0;
incr[m] = 1;
limit[m] = 2;
}
}
BaseClass::~BaseClass(void)
{
}
template<int M> void BaseClass::LoopMethod( )
{
for( idx[M]; idx[M] < limit[M]; idx[M] += incr[M] )
{
cout << "LoopMethod Nr " << M-1 << " is called." << endl;
LoopMethod<M-1>();
}
}
template<> void BaseClass::LoopMethod<0>(void)
{
idx[0] = 0;
for( idx[0]; idx[0] < limit[0]; idx[0] += incr[0] )
{
// do something
cout << "Now the inner loop is executed" << endl;
}
}
Implementation of the main-function:
#include<cstdlib>
#include "BaseClass.h"
using namespace std;
int main()
{
BaseClass baseObj;
baseObj.LoopMethod<1>();
system("PAUSE");
return 0;
}
But the solution I am searching for is to have a template class with a template method “LoopMethod” owing its own template parameter which tells the compiler how many times to nest the for-Loop. I have tried various possibilities but without success. Does anybody have a suggestion or even know a solution for this template problem?
Thanks in advance for your help,
Markus.
There are a lot of issues with your template:
What exactly is the purpose of the whole thing?
Why are you initialising the pointers with new? You know the size at compile time so why not just make them arrays?
You are not deleting the memory you are allocating
Exception safety if new fails for one of the later arrays
Implementation probably should be in the header file unless it is used for very few values of N which you instantiate
Better to use classes that exist that do this kind of thing, eg boost::array
Refactor out various sections of it.
But the solution I am searching for is
to have a template class with a
template method “LoopMethod” owing its
own template parameter which tells the
compiler how many times to nest the
for-Loop
Is that what you are asking:
template<int N>
struct X
{
template<int M>
void loop();
};
template<int N>
template<int M>
void X<N>::loop<M>()
{
}
Related
Live On Coliru
I need to implement a utility class for the purpose of lookup. The value of the internal array never changes after the initialization. My initial plan was to implement this class with the help of constexpr so that the expensive initialization can be done in compilation time. However, I am not able to come up with a good solution. So far, I can only figure out the following two methods. Both methods have drawbacks.
Method One:
The implementation looks complicate for such a simple task.
Method Two:
First, I assume the initialization is done in compilation time. Is this correct?
Second, the TwoClass::m_array really should be static instead of a member variable.
Is there a better way to implement this with c++20?
Thank you
#include <iostream>
#include <array>
using namespace std;
//== Method One
class OneClass
{
public:
uint32_t get(size_t index)
{
return m_array[index % 0xFF];
}
struct init_static_array
{
init_static_array()
{
// std::cout << "call init_static_array\n";
for (int i = 0; i < N; i++) {
m_array[i] = i * i + 10;
}
}
};
private:
static init_static_array m_init_static_array;
enum {N = 255};
static int m_array[N]; // this is a lookup table and NEVER will be changed!
};
int OneClass::m_array[] = {0};
OneClass::init_static_array OneClass::m_init_static_array{};
//== Method Two
class TwoClass
{
public:
constexpr TwoClass()
{
//std::cout << "call TwoClass::TwoClass()\n";
for (int i = 0; i < N; i++) {
m_array[i] = i * i + 10;
}
}
int get(size_t index) const
{
return m_array[index % 0xFF];
}
private:
enum {N = 255};
int m_array[N] {0}; // this is a lookup table and NEVER will be changed!
};
int main()
{
OneClass oneclass;
cout << "1 => " << oneclass.get(1) << std::endl;
cout << "256 => " << oneclass.get(256) << std::endl;
cout << "==================\n";
TwoClass twoclass;
cout << "1 => " << twoclass.get(1) << std::endl;
cout << "256 => " << twoclass.get(256) << std::endl;
return 0;
}
Output:
call init_static_array
1 => 11
256 => 11
==================
call TwoClass::TwoClass()
1 => 11
256 => 11
If it's C++20, don't you just want this:
namespace {
constexpr std::size_t N{255u};
consteval std::array<int, N> initArr()
{
std::array<int, N> arr{};
for (int i = 0; i < N; i++) {
arr[i] = i * i + 10;
}
return arr;
}
}
class C
{
private:
constexpr static std::array<int, N> arr{initArr()};
public:
constexpr C() = default;
int get(std::size_t n) const {return arr[n%255];}
};
Neither of your methods initialized the array at compile-time.
In the first method, the array is initialized in construction of static data member m_init_static_array, e.g. before main is called.
In the second method, constexpr in function declarations, including constructors, indicates that you want them being able to be called at compile-time, e.g. in evaluation of constant expressions. It doesn't mean all invocations are evaluated at compile-time. To call constexpr functions as compile-time, you have to call them in constant expression.
One solution is to initialize the static constexpr data member internal_array of type std::array by a lambda:
#include <array>
class Demo {
public:
int get(int index) const {
return internal_array[index % N];
}
private:
static inline constexpr int N = 255;
static inline constexpr std::array<int, N> internal_array = []() {
// Cannot call non-constexpr functions at compile-time
// std::cout << "std::cout << "call init_static_array\n";
std::array<int, N> arr;
for (int i = 0; i < N; ++i)
arr[i] = i * i + 10;
return arr;
}();
};
int main() {
Demo demo;
return demo.get(10);
}
I would like to return an array to a pointer, in a virtual function that is a member of a derived class of a template class. In details, my classes definition is:
Sampler.h
#ifndef SAMPLER_H
#define SAMPLER_H
template <class T>
class Sampler
{
public:
virtual T getnumber()=0;
virtual T* simulation(int n)=0;
};
class UniformSampler:public Sampler<double>
{
public:
virtual double getnumber();
virtual double* simulation(int n);
UniformSampler(double a=0.0, double b=1.0);
private:
double low_bound;
double up_bound;
};
#endif
The class Sampler is a template class in order to be able to derive an other sampler with vectors later. The implementation is:
Sampler.cpp
#include "Sampler.h"
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
//Uniform
UniformSampler::UniformSampler(double a, double b)
{
low_bound=a;
up_bound=b;
}
double UniformSampler::getnumber()
{
int myrand=rand();
while((myrand==0)||(myrand==RAND_MAX)){myrand = rand(); } //We want a number in (0, RAND_MAX).
double myuni = myrand/static_cast<double>(RAND_MAX); //Create a number in (0,1).
return low_bound + myuni*(up_bound-low_bound);
}
double* UniformSampler::simulation(int n){
double simulations[n];
for(int i=0; i<n; i++){
simulations[i] = this->getnumber();
}
return simulations;
}
My problem is that, when I try to call this program in the main(), it looks like the assignment of the pointer doesn't work. Here is my main.cpp:
#include <iostream>
#include <math.h>
#include <cstdlib>
#include <time.h>
using namespace std;
#include "Sampler.h"
int main(){
srand(time(0));
int n=10;
double *unif = new double[n];
UniformSampler uni;
unif = uni.simulation(n);
for ( int i = 0; i < n; i++ ) {
cout << "*(p + " << i << ") : ";
cout << *(unif + i) << endl;
}
delete[] unif;
return 0;
}
When I run it, it doesn't print any of the elements that unif points to. I don't understand what is wrong there.
UniformSampler::simulation is twice wrong:
double simulations[n]; uses VLA extension, so not C++ standard compliant.
you return pointer on local variable, so dangling pointer.
Solution: use std::vector instead.
#include <vector>
template <class T>
class Sampler
{
public:
virtual ~Sampler() = default;
virtual T getnumber() = 0;
virtual std::vector<T> simulation(int n) = 0;
};
class UniformSampler:public Sampler<double>
{
public:
explicit UniformSampler(double a=0.0, double b=1.0);
double getnumber() overrid;
std::vector<double> simulation(int n) override
{
std::vector<double> res(n);
for (auto& val : res){
res = getnumber();
}
return res;
}
private:
double low_bound;
double up_bound;
};
int main(){
srand(time(0));
constexpr int n = 10;
UniformSampler uni;
auto unif = uni.simulation(n);
for (int i = 0; i < n; i++ ) {
std::cout << "p[" << i << "]: " << unif[i] << endl;
}
}
What I'm trying to create is a TestScore Template class that just simply calculates the average of a array. I'm trying to throw a exception when a grade is negative or bigger than 100. I have created a NegativeScore exception class and a TooLargeScore exception class,both which just return a string message. In main, i create my array and ask the user for the grades, then use the class to get the average but for some reason it doesnt find the average. It doesnt print out the average when i try to. Im thinking the problem lies with my pointers but i dont know what the exact problem is, anyone know?
#ifndef TESTSCORES_H_INCLUDED
#define TESTSCORES_H_INCLUDED
#include <iostream>
#include "NegativeScore.h"
#include "TooLargeScore.h"
#include <iomanip>
using namespace std;
template <class T>
class TestScores
{
private:
T* testscores[];
public:
TestScores(T testscores[]);
T GetAverage();
};
template <class T>
TestScores<T>::TestScores(T testscores[])
{
*(this->testscores) = testscores;
}
template <class T>
T TestScores<T>::GetAverage()
{
T average;
T sum;
T counter;
for(int i = 0; i <= 5; i++)
{
if(*testscores[i] < 0)
{
throw NegativeScore("Test Score is negative, its invalid!");
}
else if(*testscores[i] > 100)
{
throw TooLargeScore("Test score it too high, its invalid!");
}
else
{
sum = sum + *testscores[i];
}
counter++;
}
average = sum / 5;
return average;
}
MAIN
int main()
{
int MAX = 5;
double scores[MAX];
for(int i = 0; i < MAX; i++)
{
int score;
cout << "Enter the test score for test "<< (i+1) << endl;
cin >> score;
scores[i] = score;
}
try
{
TestScores<double> tests(scores);
tests.GetAverage();
cout << tests.GetAverage() << endl;
}
catch(NegativeScore ex)
{
cout << ex.getMessage() << endl;
}
catch(TooLargeScore ex2)
{
cout << ex2.getMessage() << endl;
}
return 0;
}
Your problem is that you class holds an array of pointer to T, but you attempt to initialize it with a array of double (i.e. array of T values).
template <class T>
class TestScores
{
private:
T* testscores[];
public:
TestScores(T testscores[]);
T GetAverage();
};
template <class T>
TestScores<T>::TestScores(T testscores[])
{
*(this->testscores) = testscores; // <--- This is not doing what you think it is.
}
I am surprised that compiled, and you should strongly consider using a better compiler that will warn you of dubious operations.
You should change the class to hold a plain pointer-to-T, i.e. a T* testscores;, or better, an std::vector<T>.
For example, I could get your code working with this change:
template <class T>
class TestScores
{
private:
T* testscores; // Note simpler pointer to first element of array of length of 5.
public:
TestScores(T testscores[]);
T GetAverage();
};
You also have an error in the limits of your for loop in GetAverage (should not include 5), and your variables in that function are uninitialized and may hold garbage values.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Hey I have written code and I don't know why it is not working, it suppose to count number of memory reservations but I have done something wrong (I mean no of memory allocations is equal to 0 in both counters) and I can't spot the problem, I will appreciate any help. First post here so please be patient. :D
#include <iostream>
#include <vector>
using std::cout; using std::endl;
struct A
{
int a;
static int nr;
void * operator new[](std::size_t n) {++nr; return ::new char[n]; }
};
struct B
{
double b;
static int nr;
void * operator new[](std::size_t n) {++nr; return ::new char[n]; }
};
int A::nr = 0, B::nr = 0;
int main()
{
std::vector<A> vecA;
std::vector<B> vecB;
for (int i{}; i < 1000; i++)
{
vecA.push_back(A());
vecB.push_back(B());
}
cout << "Size of vecA: " << vecA.size() * sizeof(A) << ", number of times that memory was allocated: " << A::nr << endl;
cout << "Size of vecB: " << vecB.size() * sizeof(B) << ", number of times that memory was allocated: " << B::nr << endl;
return 0;
}
To count the number of memory reallocation I only see creation of own allocator class. Something like:
template <typename T>
class countingAllocator : public std::allocator<T>
{
public:
template<typename _Tp1>
struct rebind
{
typedef countingAllocator<_Tp1> other;
};
T* allocate(size_t n, const void *hint = 0)
{
T::nr++;
return std::allocator<T>::allocate(n, hint);
}
countingAllocator() : std::allocator<T>()
{ }
countingAllocator(const countingAllocator &a) : std::allocator<T>(a)
{ }
template <class U>
countingAllocator(const countingAllocator<U> &a) : std::allocator<T>(a)
{ }
~countingAllocator()
{ }
};
// Fix for VS Debug build Don`t need for Release
template <>
class countingAllocator<std::_Container_proxy> : public
std::allocator<std::_Container_proxy>
{
public:
template <class U>
countingAllocator(const countingAllocator<U> &a) :
std::allocator<std::_Container_proxy>(a)
{ }
};
std::vector<A, countingAllocator<A>> vecA;
std::vector<B, countingAllocator<B>> vecB;
for (int i{}; i < 1000; i++)
{
vecA.push_back(A());
vecB.push_back(B());
}
Output:
Size of vecA: 4000, number of times that memory was allocated: 18
Size of vecB: 8000, number of times that memory was allocated: 18
You could try this:
#include <vector>
#include <iostream>
struct A
{
int a;
static int nr;
};
struct B
{
double b;
static int nr;
};
int A::nr = 0, B::nr = 0;
int main ()
{
std::vector<A> vecA;
std::vector<B> vecB;
size_t A_capacity = 0, B_capacity = 0;
for (int i{}; i < 1000; i++)
{
vecA.push_back(A());
if (vecA.capacity () != A_capacity)
{
++A::nr;
A_capacity = vecA.capacity ();
}
vecB.push_back(B());
if (vecB.capacity () != B_capacity)
{
++B::nr;
B_capacity = vecB.capacity ();
}
}
std::cout << "A: " << A::nr << ", B: " << B::nr;
}
Output:
A: 11, B: 11
Live demo
I have a (what should be simple) assignment in my C++ class.
Here is the assignment:
Create a class template that contains two private data members: T * array and int size. The class uses a constructor to allocate the array based on the size entered. There is member function that allows the user to fill in the array based on the size. In addition, there is a member function that sorts the array and displays the sorted elements. Use the destructor to delete the array. Develop the main( ) to create two objects to call member functions. As a result, the first object will hold its array of double type, and the other will hold its array of the int type.
Here is what I have came up with but coming up with an error of "Allocation of incomplete type 'T'":
#include <iostream>
#include <new>
#include <vector>
using namespace std;
template <class T>
class DynArray {
protected:
int size;
T ** DynamicArray = new T[size];
public:
DynArray(){
void CreateArray(){
cout << "Enter size of Array: ";
cin >> size;
for (int i = 0; i < size; ++i){
DynamicArray[i] = new T();
}
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];}
}
//Sort Array
void Sort(T a[], int size)
{
int idx, pass;
for (pass=0; pass<size; ++pass){
for (idx=0; idx<size-1; ++idx){
if (a[idx] > a[idx+1])
swap(a[idx], a[idx+1]);}
}
for (int i=0; i<size; ++i) {
for (idx = 0; idx<size-1; ++idx) {
cout << a[idx] << " ";
}
}
}
void DeleteArray(){
for (int i = 0; i < size; ++i){
delete DynamicArray[i];
}
delete[] DynamicArray;
}
};
int main() {
DynArray<class T>();
return 0;
}
Not sure if I am a complete retard in my line of thinking or if I am just missing a small element. Any help is great.
Thank you #jblixr and #user3655463 for your help. I got it worked out I think after your hints and help.
Here is what I came up with for reference if anyone else is working on this.
#include <iostream>
#include <new>
#include <algorithm>
using namespace std;
//Template Class T
template <class T>
class DynArray {
protected:
int size;
T * DynamicArray;
public:
DynArray(){};
DynArray(size_t s): size(s) {
DynamicArray = new T[size];
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];
}
}
//Sort Array
void Sort(){
sort(DynamicArray, DynamicArray+size);
for (int i=0; i<size; i++) {
cout << DynamicArray[i] << endl;
}
}
//Clear Heap
~DynArray() {
delete []DynamicArray;
}
};
int main() {
int sizeOfArry;
cout << "Enter size of Array: ";
cin >> sizeOfArry;
//Use as an int Array;
DynArray<int> intArray = DynArray<int>(sizeOfArry);
intArray.Sort();
}
From description you have provided looks to me you want to do sth like that:
#include <iostream>
#include <algorithm>
using namespace std;
template <class T>
class DynArray {
protected:
int size;
T * DynamicArray;
public:
DynArray(size_t s): size(s) {
DynamicArray = new T[s];
}
void CreateArray(){
size_t size;
cout << "Enter size of Array: ";
cin >> size;
if(size > this->size)
size = this->size;
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];
}
}
//Sort Array
void Sort()
{
std::sort(DynamicArray, DynamicArray+size);
}
DynArray() {
delete []DynamicArray;
}
};
int main() {
DynArray<double> dob(3);
DynArray<int> di(3);
dob.CreateArray();
di.CreateArray();
dob.Sort(); di.Sort();
}
I am wondering that whether you are creating a one dimensional array or 2D array, your initial requirements states one dimensional array but you are using 2D array in your code. Anyway, I play along with one dimensional array.
error: allocation of incomplete type 'T'
T *DynamicArray = new T[size];
What you are trying to do here is in-class initialization which can be done for static data members and it is an c++11 extension for non-static data member. So I suggest you not to do so since you are learning. You can only declare the members and don't initialize here.
Even if you make static it cannot be allocated because the template type T is known only after object creation, So the compiler isn't aware of the type it is going to allocate during the compile time.
So it should be simply as
T *DynamicArray;
Nested functions
C++ doesn't support nested functions, learn C++ syntax.
Usage of constructors and destructors
A constructor will do the functionality of CreateArray() and the destructor will do the functionlaity of DeleteArray()
Instantiating a template class
You should explicitly mention the type within the angle brackets that the template class is going to use
DynArray<int> intArray; // if you want to use int
DynArray<float> floatArray;
You can also use your own custom class for type T, hope you will learn soon in your class.
DynArray<MyCustomClass> customArray;
If you correct all these things then your final skeleton will be like the below one
template <class T>
class DynArray {
protected:
int size;
T *DynamicArray ;
public:
DynArray() {
// initailize DynamicArray here
// use your CreateArray() code here
}
void sort() {
// your own sort logic
// No need to pass the size to this function, its a member function
}
~DynArray() {
// use your DeleteArray() code here
}
};
int main() {
DynArray<int> intArray;
intArray.sort()
return 0;
}
Simple, isn't it? :)