Strategy design pattern in C++ using unique_ptr

The name of the pictureThe name of the pictureThe name of the pictureClash 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 double and takes double as 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 Neuron instance

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.







share|improve this question



















  • No need for a destructor.
    – Cris Luengo
    May 3 at 0:36
















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 double and takes double as 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 Neuron instance

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.







share|improve this question



















  • No need for a destructor.
    – Cris Luengo
    May 3 at 0:36












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 double and takes double as 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 Neuron instance

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.







share|improve this question











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 double and takes double as 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 Neuron instance

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.









share|improve this question










share|improve this question




share|improve this question









asked May 2 at 19:15









LRDPRDX

2366




2366











  • 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




No need for a destructor.
– Cris Luengo
May 3 at 0:36










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.






share|improve this answer





















    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    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






























    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.






    share|improve this answer

























      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.






      share|improve this answer























        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.






        share|improve this answer













        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.







        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered May 3 at 9:13









        JDługosz

        5,047731




        5,047731






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            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













































































            Popular posts from this blog

            Python Lists

            Aion

            JavaScript Array Iteration Methods