Reputation: 335
I am reading Item 47 in "Effective C++". In the book it is suggested that the so called non-local static objects should be used with special care. Instead it suggests to use something like below:
Directory& tempDir()
{
static Directory td;
return td;
}
I am not so sure if it should be called as singleton. However, I am thinking how I can pass arguments to the constructor of class Directory. For instance, I want to pass a path as a string to Directory td, perhaps I need to do it like this:
Directory& tempDir(std::string & str)
{
static Directory td(str);
return td;
}
The problem is that whenever I want to access Directory td, I have to pass the string as the input argument. This is not so beautiful.
Does anyone have more elegant way of doing this?
Thank you.
Upvotes: 2
Views: 1695
Reputation: 206707
My suggestion.
Keep the first version of tempDir
.
Directory& tempDir()
{
static Directory td;
return td;
}
Add a member function to Directory
to set the path. When you need to set the path, use:
tempDir().setPath(path);
Using this approach allows creation of singletons that have state. You can get and set other state associated with the singleton using similar accessor and modifier functions.
Upvotes: 0
Reputation: 6834
I presume that you wish to initialize the global instance, but then access it as a singleton.
You can do it like this:
class Directory
{
public:
Directory& tempDir(const std::string & str)
{
if (tempDir_ == nullptr)
{
tempDir_ = new Directory(str);
}
return *tempDir_;
}
Directory& tempDir()
{
assert(tempDir_);
// Or throw an execption etc.
return *tempDir_;
}
private:
Directory(const std::string & str)
{
// etc.
}
static Directory* tempDir_;
};
Obviously, you need to make sure that initialization call does happen first, or restructure the approach.
Also, you might prefer to change tempDir(const std::string & str)
to initialiseTempDir(const std::string & str)
or some such.
Upvotes: 0
Reputation: 60999
Does anyone have more elegant way of doing this?
Instead of passing the path in the function, write a global function which "generates" the path:
char const* get_path()
{
// do_stuff and return the path
}
Directory& tempDir()
{
static Directory td(get_path());
return td;
}
The better way would be not to use a singleton though. Create the object in the main()
-function, initialize it there and pass it by reference for all components.
You can of course have default parameter values like
Directory& tempDir(const std::string & str = "")
, if this is of any help for your use case.
That's nonsense. Creating a temporary every time you call this function is completely unnecessary overhead.
Upvotes: 3