Strategy design pattern in C++ using unique_ptr

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
1. Introduction
This is for my ANN project.
Each building block of ANN, neuron, has activation function which determines how to get the output given the input (see formula in on repo I linked).
I have abstract class Neuron which represents a neuron in ANN. The following points have been taken into account:
- Not only activation function is intended to be used but its derivative also
- Activation function (and its derivative) returns
doubleand takesdoubleas the only argument - It should be easy and clear how to add and use new defined activation function
- Activation function should be initialized at the construction step of
Neuroninstance
2. Possible solution
2.1. Activation class
Each activation function is represented by an abstract class Activation:
class Activation
public :
virtual double f( double x ) = 0;
virtual double fPrime( double x ) = 0;
;
2.2. Concrete activation
Concrete activation is represented by a derived class:
class Identity : public Activation
public :
double f( double x ) return x;
double fPrime( double x ) return 1.;
;
class Sin : public Activation
public :
double f( double x ) return sin(x);
double fPrime( double x ) return cos(x);
;
class Sigmoid : public Activation
public :
double f( double x ) return 1. / ( 1. + exp( -x ) );
double fPrime( double x )
return ( 1. - f(x) ) / f(x);
;
2.3. Activation as a class member
I decided to use std::unique_ptr to store activation function as a member of Neuron class.
class Neuron
private :
std::unique_ptr<Activation> _act;
public :
Neuron( std::unique_ptr<Activation> act ) :
_act( std::move( act ) )
double Act( double x ) return _act->f( x ); //get output
double ActPrime( double x ) return _act->fPrime( x ); //get derivative of activation
//some other functions including pure virtual ones
;
2.4. Adding new activation
In order to add new activation function one "just" should create a class derived from Activation class and overwrite functions f and fPrime.
2.5. Using
Neuron n( std::make_unique<Identity>() );
n.Act( 30. );
n.ActPrime( 30. );
3. Discussion
I am pretty satisfied with this solution but what I am thinking about is is any destructor needed in this case if I use unique_ptr? If so, then what exactly?
Any critic, suggestion, correction, idea, advice etc. would be appreciate.
c++ design-patterns pointers
add a comment |Â
up vote
3
down vote
favorite
1. Introduction
This is for my ANN project.
Each building block of ANN, neuron, has activation function which determines how to get the output given the input (see formula in on repo I linked).
I have abstract class Neuron which represents a neuron in ANN. The following points have been taken into account:
- Not only activation function is intended to be used but its derivative also
- Activation function (and its derivative) returns
doubleand takesdoubleas the only argument - It should be easy and clear how to add and use new defined activation function
- Activation function should be initialized at the construction step of
Neuroninstance
2. Possible solution
2.1. Activation class
Each activation function is represented by an abstract class Activation:
class Activation
public :
virtual double f( double x ) = 0;
virtual double fPrime( double x ) = 0;
;
2.2. Concrete activation
Concrete activation is represented by a derived class:
class Identity : public Activation
public :
double f( double x ) return x;
double fPrime( double x ) return 1.;
;
class Sin : public Activation
public :
double f( double x ) return sin(x);
double fPrime( double x ) return cos(x);
;
class Sigmoid : public Activation
public :
double f( double x ) return 1. / ( 1. + exp( -x ) );
double fPrime( double x )
return ( 1. - f(x) ) / f(x);
;
2.3. Activation as a class member
I decided to use std::unique_ptr to store activation function as a member of Neuron class.
class Neuron
private :
std::unique_ptr<Activation> _act;
public :
Neuron( std::unique_ptr<Activation> act ) :
_act( std::move( act ) )
double Act( double x ) return _act->f( x ); //get output
double ActPrime( double x ) return _act->fPrime( x ); //get derivative of activation
//some other functions including pure virtual ones
;
2.4. Adding new activation
In order to add new activation function one "just" should create a class derived from Activation class and overwrite functions f and fPrime.
2.5. Using
Neuron n( std::make_unique<Identity>() );
n.Act( 30. );
n.ActPrime( 30. );
3. Discussion
I am pretty satisfied with this solution but what I am thinking about is is any destructor needed in this case if I use unique_ptr? If so, then what exactly?
Any critic, suggestion, correction, idea, advice etc. would be appreciate.
c++ design-patterns pointers
No need for a destructor.
â Cris Luengo
May 3 at 0:36
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
1. Introduction
This is for my ANN project.
Each building block of ANN, neuron, has activation function which determines how to get the output given the input (see formula in on repo I linked).
I have abstract class Neuron which represents a neuron in ANN. The following points have been taken into account:
- Not only activation function is intended to be used but its derivative also
- Activation function (and its derivative) returns
doubleand takesdoubleas the only argument - It should be easy and clear how to add and use new defined activation function
- Activation function should be initialized at the construction step of
Neuroninstance
2. Possible solution
2.1. Activation class
Each activation function is represented by an abstract class Activation:
class Activation
public :
virtual double f( double x ) = 0;
virtual double fPrime( double x ) = 0;
;
2.2. Concrete activation
Concrete activation is represented by a derived class:
class Identity : public Activation
public :
double f( double x ) return x;
double fPrime( double x ) return 1.;
;
class Sin : public Activation
public :
double f( double x ) return sin(x);
double fPrime( double x ) return cos(x);
;
class Sigmoid : public Activation
public :
double f( double x ) return 1. / ( 1. + exp( -x ) );
double fPrime( double x )
return ( 1. - f(x) ) / f(x);
;
2.3. Activation as a class member
I decided to use std::unique_ptr to store activation function as a member of Neuron class.
class Neuron
private :
std::unique_ptr<Activation> _act;
public :
Neuron( std::unique_ptr<Activation> act ) :
_act( std::move( act ) )
double Act( double x ) return _act->f( x ); //get output
double ActPrime( double x ) return _act->fPrime( x ); //get derivative of activation
//some other functions including pure virtual ones
;
2.4. Adding new activation
In order to add new activation function one "just" should create a class derived from Activation class and overwrite functions f and fPrime.
2.5. Using
Neuron n( std::make_unique<Identity>() );
n.Act( 30. );
n.ActPrime( 30. );
3. Discussion
I am pretty satisfied with this solution but what I am thinking about is is any destructor needed in this case if I use unique_ptr? If so, then what exactly?
Any critic, suggestion, correction, idea, advice etc. would be appreciate.
c++ design-patterns pointers
1. Introduction
This is for my ANN project.
Each building block of ANN, neuron, has activation function which determines how to get the output given the input (see formula in on repo I linked).
I have abstract class Neuron which represents a neuron in ANN. The following points have been taken into account:
- Not only activation function is intended to be used but its derivative also
- Activation function (and its derivative) returns
doubleand takesdoubleas the only argument - It should be easy and clear how to add and use new defined activation function
- Activation function should be initialized at the construction step of
Neuroninstance
2. Possible solution
2.1. Activation class
Each activation function is represented by an abstract class Activation:
class Activation
public :
virtual double f( double x ) = 0;
virtual double fPrime( double x ) = 0;
;
2.2. Concrete activation
Concrete activation is represented by a derived class:
class Identity : public Activation
public :
double f( double x ) return x;
double fPrime( double x ) return 1.;
;
class Sin : public Activation
public :
double f( double x ) return sin(x);
double fPrime( double x ) return cos(x);
;
class Sigmoid : public Activation
public :
double f( double x ) return 1. / ( 1. + exp( -x ) );
double fPrime( double x )
return ( 1. - f(x) ) / f(x);
;
2.3. Activation as a class member
I decided to use std::unique_ptr to store activation function as a member of Neuron class.
class Neuron
private :
std::unique_ptr<Activation> _act;
public :
Neuron( std::unique_ptr<Activation> act ) :
_act( std::move( act ) )
double Act( double x ) return _act->f( x ); //get output
double ActPrime( double x ) return _act->fPrime( x ); //get derivative of activation
//some other functions including pure virtual ones
;
2.4. Adding new activation
In order to add new activation function one "just" should create a class derived from Activation class and overwrite functions f and fPrime.
2.5. Using
Neuron n( std::make_unique<Identity>() );
n.Act( 30. );
n.ActPrime( 30. );
3. Discussion
I am pretty satisfied with this solution but what I am thinking about is is any destructor needed in this case if I use unique_ptr? If so, then what exactly?
Any critic, suggestion, correction, idea, advice etc. would be appreciate.
c++ design-patterns pointers
asked May 2 at 19:15
LRDPRDX
2366
2366
No need for a destructor.
â Cris Luengo
May 3 at 0:36
add a comment |Â
No need for a destructor.
â Cris Luengo
May 3 at 0:36
No need for a destructor.
â Cris Luengo
May 3 at 0:36
No need for a destructor.
â Cris Luengo
May 3 at 0:36
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
1
down vote
This looks like a standard use of PIMPL. Is that all the member functions you need? If just 2 or 3, just manually forwarding each one is fine.
Does the Activation class do anything besides have those forwarding functions? If not, donâÂÂt bother with the wrapper and forwarding at all! Just make an instance of the concrete class and use it. (If there are other functions, see if they can simply be non-virtual in the base and inherited)
Correct, unique_ptr has a destructor â that is part of its defining nature. DonâÂÂt write one for the class, and the compiler knows it should just call the destructors of all the members.
The usage is a little clumsy:
Neuron n( std::make_unique<Identity>() );
How about adding a wrapper so you can write
auto n = Neuron_with<Identity>();
As a matter of style, leading underscores are generally criticized here. Some compilers had and still support special keywords and extensions in this format. You have to remember to never use a capital initial letter after the underscore.
It is perfectly OK and idiomatic to just name the constructor arguments the same as the members.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
This looks like a standard use of PIMPL. Is that all the member functions you need? If just 2 or 3, just manually forwarding each one is fine.
Does the Activation class do anything besides have those forwarding functions? If not, donâÂÂt bother with the wrapper and forwarding at all! Just make an instance of the concrete class and use it. (If there are other functions, see if they can simply be non-virtual in the base and inherited)
Correct, unique_ptr has a destructor â that is part of its defining nature. DonâÂÂt write one for the class, and the compiler knows it should just call the destructors of all the members.
The usage is a little clumsy:
Neuron n( std::make_unique<Identity>() );
How about adding a wrapper so you can write
auto n = Neuron_with<Identity>();
As a matter of style, leading underscores are generally criticized here. Some compilers had and still support special keywords and extensions in this format. You have to remember to never use a capital initial letter after the underscore.
It is perfectly OK and idiomatic to just name the constructor arguments the same as the members.
add a comment |Â
up vote
1
down vote
This looks like a standard use of PIMPL. Is that all the member functions you need? If just 2 or 3, just manually forwarding each one is fine.
Does the Activation class do anything besides have those forwarding functions? If not, donâÂÂt bother with the wrapper and forwarding at all! Just make an instance of the concrete class and use it. (If there are other functions, see if they can simply be non-virtual in the base and inherited)
Correct, unique_ptr has a destructor â that is part of its defining nature. DonâÂÂt write one for the class, and the compiler knows it should just call the destructors of all the members.
The usage is a little clumsy:
Neuron n( std::make_unique<Identity>() );
How about adding a wrapper so you can write
auto n = Neuron_with<Identity>();
As a matter of style, leading underscores are generally criticized here. Some compilers had and still support special keywords and extensions in this format. You have to remember to never use a capital initial letter after the underscore.
It is perfectly OK and idiomatic to just name the constructor arguments the same as the members.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
This looks like a standard use of PIMPL. Is that all the member functions you need? If just 2 or 3, just manually forwarding each one is fine.
Does the Activation class do anything besides have those forwarding functions? If not, donâÂÂt bother with the wrapper and forwarding at all! Just make an instance of the concrete class and use it. (If there are other functions, see if they can simply be non-virtual in the base and inherited)
Correct, unique_ptr has a destructor â that is part of its defining nature. DonâÂÂt write one for the class, and the compiler knows it should just call the destructors of all the members.
The usage is a little clumsy:
Neuron n( std::make_unique<Identity>() );
How about adding a wrapper so you can write
auto n = Neuron_with<Identity>();
As a matter of style, leading underscores are generally criticized here. Some compilers had and still support special keywords and extensions in this format. You have to remember to never use a capital initial letter after the underscore.
It is perfectly OK and idiomatic to just name the constructor arguments the same as the members.
This looks like a standard use of PIMPL. Is that all the member functions you need? If just 2 or 3, just manually forwarding each one is fine.
Does the Activation class do anything besides have those forwarding functions? If not, donâÂÂt bother with the wrapper and forwarding at all! Just make an instance of the concrete class and use it. (If there are other functions, see if they can simply be non-virtual in the base and inherited)
Correct, unique_ptr has a destructor â that is part of its defining nature. DonâÂÂt write one for the class, and the compiler knows it should just call the destructors of all the members.
The usage is a little clumsy:
Neuron n( std::make_unique<Identity>() );
How about adding a wrapper so you can write
auto n = Neuron_with<Identity>();
As a matter of style, leading underscores are generally criticized here. Some compilers had and still support special keywords and extensions in this format. You have to remember to never use a capital initial letter after the underscore.
It is perfectly OK and idiomatic to just name the constructor arguments the same as the members.
answered May 3 at 9:13
JDÃ Âugosz
5,047731
5,047731
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193491%2fstrategy-design-pattern-in-c-using-unique-ptr%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
No need for a destructor.
â Cris Luengo
May 3 at 0:36