I am trying to parallelize a 'for' loop in the class member function. I want one of the private data member to be treated as thread-private variable. Here is my code:
// Class declaration
// MyClass.hpp file
class MyClass
{
// public data and function members
public:
struct myVar {
int g_data[576];
int h_data[576];
};
void myFun();
// Copy Constructor
inv_parfor(inv_parfor const&) = delete;
// Assignment Operator
inv_parfor& operator= (inv_parfor const&) & = delete;
private:
myVar avar;
};
// MyClass.cpp file
// Constructor
MyClass ::MyClass() :
myVar()
{
}
void MyClass::myFun(){
// some code
#pragma omp parallel for num_threads(2 > omp_get_max_threads() ? omp_get_max_threads() : 2) private(avar))
{
for (i = 0; i < 8; i++) {
smax = (static_cast<int>(i) + 1.0) * 25.3 * 100.0;
k = t_size[0] * t_size[1];
for (b_n = 0; b_n < k; b_n++) {
avar.g_data[b_n] = avar.t_data[b_n] * smax;
}
// some code
}
}
However, I'm not able to compile this code. I am getting the compilation error: only a variable or static data member can be used in a data-sharing clause.
Is this not allowed? could anyone please suggest solution for this?
I tried to declare the data member 'avar' as static:
static myVar avar;
But then I am getting the compilation error: cannot initialize static class data via constructor
Related
I'm writing a C++ Class with provides a pool of buffers. The class contains the actual (private) pool and a public function with return a pointer to a free buffer. The class declaration is within a hpp file.
CTransmissionBuffers.hpp
class CTransmissionBuffers {
public:
static constexpr uint32_t buffer_length = 1000;
struct Transmissionbuffer_T
{
osMutexId mutex;
uint8_t data[buffer_length];
osThreadId thread_id;
};
CTransmissionBuffers();
virtual ~CTransmissionBuffers();
static bool Init_Transmission_Buffers();
static Transmissionbuffer_T* Get_New_Transmission_Buffer();
static void Free_Transmission_Buffer(Transmissionbuffer_T* pBuffer);
private:
static constexpr uint32_t n_buffer = 3;
static Transmissionbuffer_T buffer_pool[n_buffer];
};
CTransmissionBuffers.cpp
#include <CTransmissionBuffers.hpp>
CTransmissionBuffers::Transmissionbuffer_T buffer_pool[CTransmissionBuffers::n_buffer] = {}; /// this causes the problem
CTransmissionBuffers::CTransmissionBuffers()
{
// TODO Auto-generated constructor stub
}
CTransmissionBuffers::~CTransmissionBuffers()
{
// TODO Auto-generated destructor stub
}
bool CTransmissionBuffers::Init_Transmission_Buffers()
{
for (uint32_t i = 0; i < n_buffer; i++)
{
buffer_pool[i].mutex = osMutexCreate(nullptr);
if (nullptr == buffer_pool[i].mutex)
{
return false;
}
}
return true;
}
CTransmissionBuffers::Transmissionbuffer_T* CTransmissionBuffers::Get_New_Transmission_Buffer()
{
Transmissionbuffer_T* pBuffer = nullptr;
for (uint32_t i = 0; i < n_buffer; i++)
{
if (osOK == osMutexWait(buffer_pool[i].mutex, 0))
{
//Mutex erhalten
pBuffer = &(buffer_pool[i]);
break;
}
}
return pBuffer;
}
void CTransmissionBuffers::Free_Transmission_Buffer(Transmissionbuffer_T* pBuffer)
{
if(nullptr == pBuffer)
{
return;
}
osMutexRelease(pBuffer->mutex);
}
After compiling this I got a undefined reference to buffer_pool, so I tried to add a
CTransmissionBuffers::Transmissionbuffer_T buffer_pool[CTransmissionBuffers::n_buffer] = {};
to the corresponding cpp file but a can't access n_buffer because it's private :(
Do I have to define a static member? Do you have some good ideas how to solve this problem?
Greets Julian
Your syntax is off. Transmissionbuffer_T is not a member of your class, but is the type of a member of your class. A static definition should look like this:
Transmissionbuffer_T CTransmissionBuffers::buffer_pool[CTransmissionBuffers::n_buffer]={};
In C++17 you can use an inline variable as a more convenient way to work around this issue:
class CTransmissionBuffers {
//...
private:
//...
inline static Transmissionbuffer_T buffer_pool[n_buffer];
}
If you declare it an inline variable, do not also declare the variable in the outside the class or you'll have duplicate definitions and get an error.
Note: constexpr static members are implicitly inline, so don't need to do anything for n_buffer to work correctly.
after doing some reasearch it turns out that inline variables are only supported with gcc 7
(see https://gcc.gnu.org/projects/cxx-status.html)
I'm stuck with gcc6 however.
I initialised the buffers by placing a
CTransmissionBuffers::Transmissionbuffer_T CTransmissionBuffers::buffer_pool[n_buffer] = {};
at the beginning of the cpp file. That seams to work. Thanks alot for your help :)
i was wondering if is possible make that a method of class points to another method of other class:
consider this:
// Class Foo:
class Foo
{
static int GetA(int a);
static int GetB(int b);
};
int Foo::GetA(int a)
{
return a * 2;
}
int Foo::GetB(int b)
{
return a * 4;
}
// Hooking class methods:
class HookFoo
{
static int HookGetA(int);
static int HookGetB(int);
};
int(HookFoo::*HookGetA)(int) = (int(HookFoo::*)(int))0x0; // (0x0 Memory address) or for example: &Foo::GetA;
int(HookFoo::*HookGetB)(int) = (int(HookFoo::*)(int))0x0; // (0x0 Memory address) or for example: &Foo::GetA;
I know it's possible do some like:
int(*NewHook)(int) = &Foo::GetA;
but how i can do for declare the methods into of a class?
Here is more or less what you tried to achieve (minimal, working example):
class Foo
{
public:
static int GetA(int a);
static int GetB(int b);
};
int Foo::GetA(int a)
{
return a * 2;
}
int Foo::GetB(int b)
{
return b * 4;
}
class HookFoo
{
public:
using FuncType = int(*)(int);
static FuncType HookGetA;
static FuncType HookGetB;
};
// Initialized with Foo::GetA
HookFoo::FuncType HookFoo::HookGetA = &Foo::GetA;
// nullptr'ed
HookFoo::FuncType HookFoo::HookGetB = nullptr;
int main() {
HookFoo::HookGetA(0);
}
For the methods in Foo are static, you can use a simple function pointer type to refer to them. You don't have to use (and can't use actually) a member function pointer in this case.
The using declaration helps to have a more readable code.
When you have correctly initialized your hooks, you can invoke them (thus the pointed functions) as you can see in the main.
I added a couple of visibility specifiers for your methods and data members were all private.
You can use function pointers.
Ex:
class A {
public:
static void say_hello() { cout << "Hello\n"; }
};
class B {
public:
static void(*hook)();
};
void(*B::hook)() = A::say_hello;
int main()
{
B::hook();
}
If you need to hook into functions at a specific address, use a function pointer. You can't reassign functions like that
// typedef your function pointers, it makes the syntax a lot easier
typedef int(*FHook)(int);
class HookFoo
{
static FHook HookGetA;
static FHook HookGetB;
};
// assign to address
FHook HookFoo::HookGetA = (FHook)0x1234;
FHook HookFoo::HookGetB = (FHook)0x5678;
Of course its your job to make sure the addresses are correct.
the explicit function pointer types would be as such:
class HookFoo
{
static int (*HookGetA)(int);
static int (*HookGetB)(int);
};
int (*HookFoo::HookGetA)(int) = (int(*)(int))0x1234;
int (*HookFoo::HookGetB)(int) = (int(*)(int))0x5678;
This is the header:
class Board {
public:
friend class Game;
Board() = default;
Board(int n) : N(n) { }
Board& SetType(int, int, char);
void GetType(int, int);
Board& CreateEmptyBoard();
void BoardDisplay();
private:
int N = 0;// dimension
char Maze[15][15];
const static int MaxSize = 15;
};
class Game {
public:
Game() = default;
Game(int x, int y) : PosX(x), PosY(y) { }
void BuildGame();
void GameDisplay();
void MoveUp();
void MoveDown();
void MoveLeft();
void MoveRight();
private:
int PosX = 0;
int PosY = 0;
};
void Game::BuildGame() {
srand(time(NULL));
for (int i = 0; i < Board::N; i++) {
for (int j = 0; j < Board::N; j++) {
if (i == rand() % (Board::N) && j == rand() % (Board::N))
Board::Board& SetType(i, j, 'W');
}
}
}
In class Game's member function void BuildGame,I want to call member functionBoard& SetType(int,int,char) in class Board.I define this function in a header file and not show here. Then I build the project, I got invalid use of non-static data member 'Board::N' and 'SetType' was not declared in this scope. Like this
Where I wrong? I can't find it.
The compiler is letting you know that you are using an instance variable as a static. A static variable is associated with an entire class and not a single object, so it is called through the class name and not an object of the class. but it would need to be marked as static like so
class Board
{
public:
static Board& setType(int, int, char);
...
private:
static int N;
...
}
my instinct however tells me that you want to use it at an instance level, so you would write your void Game::buildGame() method using a Board that it creates (possibly making it an attribute of the Game class:
void Game::BuildGame() {
//make your board here. alternatively make an instance of the game
Board myBoard();
srand(time(NULL));
//in the following, use myBoard as the instance of a board.
for (int i = 0; i < myBoard.N; i++) {
for (int j = 0; j < myBoard.N; j++) {
if (i == rand() % (myBoard.N) && j == rand() % (Board::N))
myBoard.setType(i, j, 'W');
}
}
}
And a Board class that looks something like this. You will probably want your setType method to modify the instance and return void instead of returning another board reference.
class Board
{
public:
//this one will change this particular Board instance.
void setType(int, int, char);
//this one may make sense to be static if it is a factory method
//but why not use a constructor instead?
static Board& createEmptyBoard();
//maybe you meant something to reset the board to empty state.
void resetBoardToEmpty();
...
private:
int N;
...
}
while you're at it you might make it a struct (which has members public by default) as it seems to be a "hidden" holder class for the game, and this would alleviate the need to use a friend class (these are to be used judiciously as they can get messy really fast). using a struct would also allow you to make a ChessGame class that reuses the Board struct.
N isn't a static member of class Board, hence you'll need an instance of board to access it.
Your Game class actually needs to have a Board member variable to achieve that above mentioned instance.
I have my main.cpp like this:
#include <iostream>
#include "curve1.h"
#include "curve2.h"
using namespace std;
int main()
{
Curve1 curve1Obj;
Curve2 curve2Obj;
curve1Obj.enterScores();
curve1Obj.calcAverage();
curve1Obj.output();
curve1Obj.curve();
curve1Obj.output(curve1Obj.new_getAverage1(), curve1Obj.new_getScore1());
curve2Obj.curve();
return 0;
}
Base class Score has two derived classes Curve1 and Curve2. There are two curve() functions, one is in Curve1 and other in Curve2 classes. getSize() returns the value of iSize.
My base class header score.h looks like this:
#ifndef SCORE_H
#define SCORE_H
class Score
{
private:
int *ipScore;
float fAverage;
int iSize;
public:
Score(
void enterScores();
void calcAverage();
void output();
void output(float, int*);
void setSize();
int getSize();
void setScore();
int *getScore();
float getAverage();
};
#endif
You can see that I have used curve1Obj to enter scores, calculate average and output. So if I call getSize() function with cuve1Obj, it gives the right size that I took from user in enterScores() function. Also the result is same if I call getSize() in score.cpp definition file in any of the functions (obviously).
.....
The problem is when I call curve() function of Curve2 class in main (line 23) with the object curve2Obj, it creates a new set of ipScore, fAverage and iSize (i think?) with garbage values. So when I call getSize() in curve() definition in curve2.cpp, it outputs the garbage.
.....
How can I cause it to return the old values that are set in curve1.cpp?
Here is my curve2.cpp
#include <iostream>
#include "curve2.h"
using namespace std;
void Curve2::curve()
{
cout << "getSize() returns: " << getSize() << endl; // out comes the garbage
}
Can I use a function to simply put values from old to new variables? If yes then how?
Well, basically your problem can't be easily solved the way it is.
Like you said:
1 - Don't use constructors of any type.
2 - Don't use vectors.
3 - Using dynamic new and delete etc. etc.
Use the constructors or stick with what G. Samaras and Richard Hodges said. You can only solve this that way.
There is limited information available here but I would say that your Score constructor has not initialised ipScore or iSize.
If you are hell-bent on using a pointer to a dynamically allocated array of ints for your score then at least null out the pointer in the constructor and test for null in the average function (i.e. no scores yet).
Better yet... use a std::vector of int for your scores.
Why are people still using new and delete? What the hell are they teaching in schools?
What I think you want is this:
#include <vector>
class Score {
public:
Score()
: _scores()
, _average(0)
{ }
void calcAverage() {
double total = 0;
if(auto s = _scores.size() > 0) {
for (const auto& v : _scores)
total += v;
total /= s;
}
_average = total;
}
virtual void curve() = 0;
protected:
// one of the few correct uses of 'protected' - giving limited access to data as interface to derived classes
const std::vector<double>& scores() const {
return _scores;
}
// or
std::vector<double> copyScores() const {
return _scores;
}
private:
// use doubles since you'll be doing floating point arithmetic
std::vector<double> _scores;
double _average;
};
class Curve1 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores() or copyScores() if you want to make changes to the array
}
};
class Curve2 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores();
}
};
You need to understand inheritance. Curve1 inherits from Score. Curve2 inherits from Score.
Now see this example:
#include <iostream>
class Base {
int x;
};
class A : public Base {
int a;
public:
void set_a(int arg) {
a = arg;
}
int get_a() {
return a;
}
};
class B : public Base {
int b;
public:
void set_b(int arg) {
b = arg;
}
int get_b() {
return b;
}
};
int main() {
A a_object;
a_object.set_a(4);
B b_object;
b_object.set_b(a_object.get_a());
std::cout << "a of a_object = " << a_object.get_a() << "\n";
std::cout << "b of b_object = " << b_object.get_b() << "\n";
return 0;
}
class A, has as members x and a. Class B has as members x and b.
When I create an instance of class A, I will two data members created internally, x and a.
When I create an instance of class A, I will two data members created internally, x and b.
But, the first x and the second are DIFFERENT. They are a different cell in the memory!
something like this:
class Score {
public:
Score()
: _scores(0)
, _size(0)
, _average(0)
{ }
// copy constructor
Score(const Score& rhs)
: _scores( new double[rhs._size] )
, _size(rhs._size)
, _average(rhs._average)
{
if (_size) {
for(int i = 0 ; i < _size ; ++i) {
_scores[i] = rhs._scores[i];
}
}
}
// ... and if copy constructor then always a copy operator
Score& operator=(const Score& rhs) {
// assignment in terms of copy constructor - don't repeat yourself
Score tmp(rhs);
swap(tmp);
return *this;
}
// pre c++11 we make our own swap.
// post c++11 we would make non-throwing move constructor and move-assignment operator
void swap(Score& rhs) {
// std::swap is guaranteed not to throw
std::swap(_scores, rhs._scores);
std::swap(_size, rhs._size);
std::swap(_average, rhs._average);
}
~Score()
{
delete[] _scores;
}
void calcAverage() {
double total = 0;
if(_size > 0) {
for (int i = 0 ; i < _size ; ++i)
total += _scores[i];
total /= _size;
}
_average = total;
}
virtual void curve() {};
private:
// use doubles since you'll be doing floating point arithmetic
double * _scores;
int _size;
double _average;
};
// rmember to override the copy operators and assignment operators of derived classes
// remember to call the base class's operator
Here is the problem:
Write three base class named Voltmeter, Ammeter and ResistanceMeter.
Voltmeter class will have a member function volt, a non default constructor, a copy constructor
and a function measureVolt().
Ammeter class will have a member function amp, non default constructor, a copy constructor and
a function measureCurrent().
ResistanceMeter class will have a member function resistance, non default constructor,
a copy constructor and a function measureResistance().
Now write a class Multimeter which will
have object of Voltmeter, Ammeter and ResistanceMeter so thus it can use the functionality of those class.
In my solution, the compiler say undefined reference on every object I used in the class 'multimeter'. Code is as below:
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
class voltmeter{ //class - Voltmeter
float volt;
public:
voltmeter(); //default constructor
voltmeter(float v){ //non default constructor
volt = v;
}
voltmeter(voltmeter &ob) //copy constructor
{
volt = ob.volt;
}
void set_volt(float v)
{
volt = v;
}
float get_volt(void)
{
return volt;
}
void measure_volt(void) //measureVolt()
{
cout<<"Current volt in the circuit is: "<<volt<<"V"<<endl;
}
};
class ameter
{
float amp;
public:
ameter();
ameter(float a)
{
amp = a;
}
ameter(ameter &ob)
{
amp = ob.amp;
}
void measure_current(void)
{
cout<<"Current flow in circuit is: "<<amp<<"amp"<<endl;
}
void set_amp(float a)
{
amp = a;
}
float get_amp(void)
{
return amp;
}
};
class res_meter //class - resistanceMeter
{
float resistance;
public:
res_meter();
res_meter(float res)
{
resistance = res;
}
res_meter(res_meter &ob)
{
resistance = ob.resistance;
}
float get_resistance(void)
{
return resistance;
}
void set_resistance(float res)
{
resistance = res;
}
void meas_res(void)
{
cout<<"Current resistance in circuit is "<<resistance<<"ohm"<<endl;
}
};
class multimeter
{
res_meter r1;
ameter a1;
voltmeter v1;
public:
multimeter(){
r1.set_resistance(12.30);
a1.set_amp(22.5);
v1.set_volt(26.9);
}
// ~multimeter();
void show_info(void)
{
cout<<"Current Multimeter Status is as below: "<<endl;
a1.measure_current();
r1.meas_res();
v1.measure_volt();
}
};
int main()
{
multimeter M;
M.show_info();
return 0;
}
You declare a default constructor for all the classes (which is used in the multimeter class), but you never define the constructors.
Change e.g.:
class voltmeter
{
// ...
voltmeter();
// ...
};
to
class voltmeter
{
// ...
voltmeter() {}
// ...
};
In my solution, the compiler say undefined reference on every object I used in the class 'multimeter'.
Read your warning messages more carefully. The compiler is telling you that the multimeter default constructor (which is defined) is referencing the default constructors for classes ameter, res_meter, and voltmeter'. It is those default constructors that aren't defined.
So define them, or use the non-default constructors that you did define.