0

Here is my main code since it is seems that idea is not really coming across. hope this clarifies things. it consists of neural net activation functions

activation.cpp

typedef struct
{
    virtual float operator() (float x) const = 0;
    virtual float gradient (float x, float g) const = 0;

} activation;


struct sigmoid : activation
{
    float operator() (float x)
    { return 1.f / (1.f + expf(-x)); }

    float gradient(float x, float g)
    { float s = (*this)(x); return g * s * (1.f - s); }

};


struct relu : activation
{
    float operator() (float x)
    { return x; }

    float gradient(float x, float g)
    { return g; }

};

i want these functor objects to be callable as they are upon include as they will always be the same...

EG

main.cpp

#include "activation.cpp"
int main() { cout << sigmoid(0) << sigmoid.gradient(0) << endl; }

prints

0.50.25
user2255757
  • 756
  • 1
  • 6
  • 24
  • 3
    Why are they functors? – Mooing Duck Aug 01 '16 at 16:55
  • more for style and code readibility and consistency – user2255757 Aug 01 '16 at 16:55
  • i guess this question isn't just for functor objects, but more as a general instantiation question – user2255757 Aug 01 '16 at 16:57
  • https://en.wikipedia.org/wiki/Function_object Has some nice C++ snippets in it – Adam Martin Aug 01 '16 at 16:57
  • 1
    Do the same you'd do for a non-functor type. – juanchopanza Aug 01 '16 at 17:01
  • 1
    I have a feeling `A(3)` is always going to be parsed as a constructor call. You may get what you want with a lambda and passing it around by reference. – NathanOliver Aug 01 '16 at 17:01
  • thats what i dont want, is there a way to make a class you dont construct but that always default? – user2255757 Aug 01 '16 at 17:03
  • @juanchopanza what do you mean by that i am aware that what i want will be the same for object and functor i just don't know how to do it either way – user2255757 Aug 01 '16 at 17:04
  • OK, so the whole functor thing is irrelevant then. Anyway, you can't have an object without instantiating one. – juanchopanza Aug 01 '16 at 17:04
  • @user2255757 Wouldn't `cout << A(3)() << endl;` do what you want? I still don't get what you're actually asking about. – πάντα ῥεῖ Aug 01 '16 at 17:05
  • if you mean `A()(3)` then i would be instantiating a functor object every time the call is made right? – user2255757 Aug 01 '16 at 17:06
  • 2
    I think you're looking for a singleton pattern? See http://stackoverflow.com/questions/270947/can-any-one-provide-me-a-sample-of-singleton-in-c/271104#271104 – Adam Martin Aug 01 '16 at 17:06
  • 1
    @user2255757 Why not something like `A a(3);` and `cout << a() << endl;` then? – πάντα ῥεῖ Aug 01 '16 at 17:07
  • 1
    _@user2255757_ _"What i am curious about is objects you dont instantiate they are always that one object in the code. with the same behaviour"_ I have to agree with @Adam, that's a _Singleton_ actually (though it's at least instantiated once). – πάντα ῥεῖ Aug 01 '16 at 17:13
  • so the only way to achieve what i want is to initialise the object in functor.cpp and only make the singleton visible through the header file? – user2255757 Aug 01 '16 at 17:17
  • When exposing the singleton visible, the type declaration must also be visible, so if you want to make it uninitializable, that means you have to make the default constructor and copy constructor not publicly available, which means you also have to make yourself a backdoor to create your global versions.... but yes. – Mooing Duck Aug 01 '16 at 20:53

1 Answers1

1

To call a functor via A(3), then A has to be the name of an variable, not the type. Which means A has to be either a instance of the functor, which ends up complicated because the functor type is public in which case you have to forbid others from constructing and copying and taking addresses and all that. Alternatively: make A a regular function.

functors.h

int A(int x);

functors.cpp

struct AFunctor { 
    int operator()(int x) const {return 3*x;} ;
};
int A(int x) {
    static AFunctor a;
    return a(x);
}    

main.cpp

#include "functors.h"
int main() 
{cout << A(3) << endl;}

As should be obvious at this point, there's literally no reason to have a singleton functor like this. Functors are usually stateful, or you can create them left and right, or both.


Since it's now clear that you definitely want singleton functors, this would be the way to go I guess.

functors.h

struct activation
{
    virtual float operator() (float x) const = 0;
    virtual float gradient (float x, float g) const = 0;
};

struct sigmoidFunctor : activation
{
    float operator() (float x);    
    float gradient(float x, float g);
    static sigmoidFunctor& get();
private
    sigmoidFunctor()=default;
    sigmoidFunctor(const sigmoidFunctor&)=delete;
};
extern sigmoidFunctor& sigmoid;

struct reluFunctor : activation
{
    float operator() (float x);    
    float gradient(float x, float g);
    static reluFunctor& get();
private
    reluFunctor()=default;
    reluFunctor(const reluFunctor&)=delete;
};
extern reluFunctor& relu;

functors.cpp

float sigmoidFunctor::operator() (float x)
{ return 1.f / (1.f + expf(-x)); }

float sigmoidFunctor::gradient(float x, float g)
{ float s = (*this)(x); return g * s * (1.f - s); }

sigmoidFunctor& sigmoidFunctor::get() {
    static sigmoidFunctor sigmoid;
    return sigmoid;
}
sigmoidFunctor& sigmoid = sigmoidFunctor.get();


float reluFunctor::operator() (float x)
{ return x; }

float reluFunctor::gradient(float x, float g)
{ return g; }

reluFunctor& reluFunctorFunctor::get() {
    static reluFunctor relu;
    return relu;
}
reluFunctor& relu = reluFunctor.get();

As evidenced by the vast increase in complexity, I strongly urge you to reconsider. Usually, singletons just make a mess of everything.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • Whatever this should be good for :P .... – πάντα ῥεῖ Aug 01 '16 at 17:09
  • 1 not what i want, 2 there is a reason since i clearly want one. – user2255757 Aug 01 '16 at 17:10
  • 2
    @user2255757 Can you show us the reason? I fail to see why a regular function does not work. – NathanOliver Aug 01 '16 at 17:18
  • the code has been added – user2255757 Aug 01 '16 at 17:25
  • 1
    @user2255757 You changed your question radically now. That's not nice! Get it right at 1st shot and don't post arbitrary bogus code. Provide a [MCVE] instead. Now your question is put [on hold], look forward how you get out of that _schlamassel_. And BTW: The `operator()()` overload needs to be bound to an instance, period! – πάντα ῥεῖ Aug 01 '16 at 17:41
  • code is literally a more complicated version of my original question. always nice when stackoverflow users downvote questions they aren't capably of answering and thus shove under the rug as dumb or caseless question – user2255757 Aug 01 '16 at 17:46
  • 1
    @user2255757 _"always nice when stackoverflow users downvote questions they aren't capably of answering"_ Nope! That's a completely wrong perception from your side. You were _unclear_ with your original question, and actually still are, even taking your changes into account. I'm not going to vote for reopening this question. Are we mentalists or what are you expecting here actually? Be clear and specific. – πάντα ῥεῖ Aug 01 '16 at 17:51
  • well i figured out a solution no thanks to you guys will post answer now – user2255757 Aug 01 '16 at 17:55
  • @user2255757 _"will post answer now"_ too late :P – πάντα ῥεῖ Aug 01 '16 at 18:51