6

I'm trying to create a C++ singleton pattern object, using references not pointers, where the constructor takes 2 parameters

I have looked at a whole host of example codes, including: Singleton pattern in C++, C++ Singleton design pattern and C++ Singleton design pattern

I believe I understand the principles involved, but despite attempting to lift snippets of code almost directly from the examples, I cannot get it to compile. Why not - and how do I create this singleton pattern object using a constructor that takes parameters?

I have put the errors received in the code comments.

Additionally, I am compiling this program in the ARMmbed online compiler - which may/may not have c++ 11, I am currently trying to find out which.

Sensors.h

class Sensors
{
public:
     static Sensors& Instance(PinName lPin, PinName rPin); //Singleton instance creator - needs parameters for constructor I assume
private:
    Sensors(PinName lPin, PinName rPin); //Constructor with 2 object parameters
    Sensors(Sensors const&) = delete; //"Expects ;" - possibly c++11 needed?
    Sensors& operator= (Sensors const&) = delete; //"Expects ;"
};

Sensors.cpp

#include "Sensors.h"
/**
* Constructor for sensor object - takes two object parameters
**/
Sensors::Sensors(PinName lPin, PinName rPin):lhs(lPin), rhs(rPin)
{
}
/**
* Static method to create single instance of Sensors
**/
Sensors& Sensors::Instance(PinName lPin, PinName rPin)
{
    static Sensors& thisInstance(lPin, rPin); //Error: A reference of type "Sensors &" (not const-qualified) cannot be initialized with a value of type "PinName"

    return thisInstance;
}

Thanks very much!

Community
  • 1
  • 1
davidhood2
  • 1,367
  • 17
  • 47
  • This looks even *more* wrong than the usual singleton approach. Imagine this code: `Sensors::Instance(foo, bar).doSomething(); Sensors::Instance(baz, qux).doSomething();`. The second call will blatantly *ignore* the parameters, something which is not obvious at the call site *at all.* – Angew is no longer proud of SO Apr 18 '15 at 15:39
  • Would that be important? As its not supposed to create a new object but return the original, does it matter that the parameters are ignored? If the parameters should be checked, wouldn't it be simple to add a validation step in the method prior to returning the original object? – davidhood2 Apr 18 '15 at 15:44
  • 1
    The problem is that they won't follow each other as nicely in code. Let's say you see just `Sensors::Instance(alpha, beta).doSomething();` somwhere in code. You have no way of knowing whether the instance will actually have the parameters `alpha` and `beta`, or whether it will be acting on an instance created in a previous call with potentially totally different parameters. – Angew is no longer proud of SO Apr 18 '15 at 16:16

1 Answers1

7

You should create static local variable, not a reference. Change to this.

Sensors& Sensors::Instance(PinName lPin, PinName rPin)
{
    static Sensors thisInstance(lPin, rPin);     
    return thisInstance;
}

This will return the same object (created by first lPin and rPin) any time calling Sensors::Instance method.

Ashot
  • 10,807
  • 14
  • 66
  • 117
  • Thank you. I'm attempting to now create the opject as such: Sensors Sense = Sensors.Instance(p19, p20); however, apparently"Type name is not allowed in "main.cpp" - how I can instantiate my singleton object? Thanks again! – davidhood2 Apr 18 '15 at 15:45
  • 2
    You should write `Sensors& Sense = Sensors::Instance(p19, p20);` Now `Sense` refers to singleton object. – Ashot Apr 18 '15 at 15:46