I'd like to allow a class to inherit from a base CRTP class that causes a global constructor to be created and run before main() begins. The idea is to use this to register a type in some map to be looked up later. It seems that this only works if I've actually instantiated a member of the Derived class and used the Base class.
#include <iostream>
class Foo {
public:
Foo() { std::cout << "Foo" << std::endl; }
};
template <typename T>
class Bar {
private:
static Foo foo_;
};
class Test : public Bar<Test> {
};
int main() {
return 0;
}
class Test inherits from Bar<Test> which has a static member variable of type Foo. Unfortunately, Foo's constructor is not invoked. I'd like to be able to cause a global constructor to be run when a class instantiates a template using CRTP without needing to actually create an instance of that class. I'd be happy with implementation dependent solutions too.
There is no way besides SomeClass instance in a translation unit to have a global class instance.
With a template and a static member, you might (or might not) end up with globals in multiple translation unit.
If you declare a class with static fields, it doesn't matter is it template-driven or not - static members would not be instantiated unless you create an instance of such class. And be aware - time of the static members instantiation is quite tricky thing, especially if you have multiple libraries involved.
Related
If I have the following nested classes:
class foo {
public:
class bar {
public:
int barMethod() const;
protected:
int barVar;
};
protected:
int fooVar;
};
and then in a .cpp, can I implement barMethod() this way?
int foo::bar::barMethod() const {
return this->fooVar + this->barVar;
}
What I mean is:
does this keyword in a nested class refer to all classes that are upstream in hierarchy?
does this keyword in a nested class refer to all classes that are upstream in hierarchy?
No, "current" class only. Class nesting is mostly a lexical thing. Unlike in, say, Java, where an inner class can be associated with an instance of an enclosing outer class, foo::bar is pretty much like any other class that isn't nested.
If you want to associate an instance of bar with an instance of foo, you need to capture a reference or a pointer to foo in bar.
I have a base class B that is derived many times: D1, D2, etc.
In class B i would like to have a static method getInfo() that returns a BaseInfo class (basically a class containing default member values for class B) so it would make sense to make it static, since there's no need for a specific instance.
Now, is there a way to force derived classes to implement this method?
obviously each derived class has it's own default values for class members.
Ideally it would be great if in base class i could declare the getInfo() as virtual static but since there's no such thing in C++ i was wondering if there's a nice way to implement this behaviour.
I was thinking about CRTP but didn't come up with a solution.
Use the traits pattern.
template<typename T> struct base_traits;
Every class that you expect to getInfo from must specialize this type.
template<>
struct base_traits<B>
{
static BaseInfo getInfo() { return b_info; }
};
template<>
struct base_traits<D1>
{
static BaseInfo getInfo() { return d1_info; }
};
template<>
struct base_traits<D2>
{
static BaseInfo getInfo() { return d2_info; }
};
To get the BaseInfo for any particular class, you write
BaseInfo d1info = base_traits<D1>::getInfo();
If somebody forgets to specialize base_traits<T> for their derived type T, you get a compiler error.
BaseInfo d3info = base_traits<D3>::getInfo();
error: incomplete type ‘base_traits<D3>’ used in nested name specifier
It would make sense to make it static, since there's no need for a specific instance.
There is in fact a need in a specific instance. Specifically, there is a need in the run-time type information stored in the instance. The only possible choice is to make the function virtual, and override it in derived classes.
We are in the process of deprecating ACE libraries in our project which consists of around 120 binaries and in many of binaries we have used ACE_Singleton.Since after deprecating we will not have this class so we are thinking of writing our own generic singleton in our shared library that is common across all these binaries and one of the goals that we want to achieve is if somebody inherit from this class (using CRTP) say Logger and even when Logger constructor is public then also we cannot create two logger object.
To illustrate let's assume my singleton class name is GenericSingleton and my client class is logger then following code should throw error :
class Logger:public GenericSingleton<Logger>
{
public:
Logger()
{
}
};
int main()
{
Logger obj;// first instance no issue
Logger obj1; // second instance is problem as it is inherited from singleton
}
So can somebody suggest me how GenericSingleton should be designed so that while creating second object i should get compiletime error ?
In short is there a way that if my derived class doesn't have private constructor,destructor copy constructor etc. then it can be checked at compiletime using static_assert ?
There's no way for a constructor to know at compile time where or how many times it will be called; constructors are just functions, and functions don't know anything about their contexts. Consider that any static_asserts will be evaluated when the class is compiled, but this can (and almost certainly will!) happen in an entirely different translation unit from code that actually instantiates the class.
In any case, it seems unlikely that this would be helpful, because you must have some way to access singletons throughout your codebase.
Additionally, it's unclear why you want to permit your singletons to have public constructors. If you want to enforce singleton behavior at compile time for a completely arbitrary class just by adding an inheritance declaration, you're out of luck; arbitrary classes can be, well, arbitrarily constructed.
Since you're transitioning from the ACE singleton, I suggest you use a similar API; note that the ACE singleton documentation recommends making your singleton constructors private.
If, however, you just want some way to force your client to write a constructor that can't (easily) be called improperly, you can do something like this:
template <typename T>
class SingletonBase {
protected: class P { friend class SingletonBase<T>; P() = default; };
public:
SingletonBase(P) {}
static T& Instance() {
static T instance { P {} };
return instance;
}
};
(You will also need to delete the base class's copy and move constructors. Here is a working example use case. Note that declaring P's constructor =default does not prevent the singleton class from default-initializing instances of P. )
Now, because the base class constructor takes an argument of type P, the singleton class implementation must pass a P to its parent class constructor. But since the constructor for P is private, the singleton class won't be able to construct an instance of P except by copy or move construction, so its constructor must take an instance of P. But since P itself is protected, only the singleton class and the parent class can actually use it, so effectively the only possible call to the child's constructor must be in the Instance method.
Note that you do not need to explicitly declare and define the singleton-class's constructor, which would be ugly because of the need to use SingletonBase<Singleton>::P. You can simply expose the constructor with a using declaration:
using BASE = SingletonBase<Myclass>;
using BASE::SingletonBase;
You need to make sure that instances of Logger cannot be created outside the function that creates the sole instance of Logger.
Here's a simple implementation.
template <typename T> class GenericSingleton {
public:
static T& instance() {
static T instance_;
return instance_;
}
};
class Logger: public GenericSingleton<Logger>
{
// Make sure that the base class can create the sole instance of
// this class.
friend GenericSingleton<Logger>;
private:
// Makes sure that you cannot create objects of the class
// outside GenericSingleton<Logger>
~Logger() {}
public:
void foo() {}
};
int main()
{
// OK. Call foo() on the only instance of the class.
Logger::instance().foo();
// Not OK.
Logger obj1;
}
My advice would be to separate concerns. There is the concept of a service (such as a logger) and the service may or may not be a singleton. But this is an implementation detail, and therefore a separate concern. The consumer of the service ought to be agnostic of it.
Now, later in the lifecycle of the project, when you realise that singletons were a terrible idea, you can refactor the singleton without having to refactor any code that depends on it.
e.g.:
template<class Impl>
struct implements_singleton
{
using impl_type = Impl;
static impl_type& get_impl()
{
static impl_type _{};
return _;
}
};
struct logger_impl
{
void log_line(std::string const& s)
{
std::clog << s << std::endl;
}
};
struct logger
: private implements_singleton<logger_impl>
{
void log_line(std::string const& s) {
get_impl().log_line(s);
}
};
void do_something(logger& l)
{
l.log_line("c");
}
int main()
{
logger a;
logger b;
a.log_line("a");
b.log_line("b"); // behind the scenes this is the same logger
// but the user need not care
do_something(a);
}
#include <iostream>
using namespace std;
class B
{
public:
virtual void acctobase() {
cout <<"base\n";
}
};
class D: public B
{
void acctobase() {
cout <<"derived\n";
}
};
int main() {
B* o = new D();
o->acctobase();//i want this function not to be accessible using derived class object
return 0;
}
I've tried private B::accatobase; but still it is accessible and also i do not want to inherit class B privately so how to change its access specifier ?
You cannot do that, by design.
Derived class must always be compatible with its base, in the sense that whatever functions you can call on a base class should be callable on all of its derived classes. This is what Liskov Substitution Principle is about. That is why you can make member functions from base class more accessible in a derived class, but you cannot make it less accessible.
You could implement the method in the derived class to throw std::logic_error();. Then any caller will receive an error at runtime. After all, you're doing something which fundamentally requires a runtime type check anyway--you can't know in general at compile time if the method should be accessible or not, so you can only make it "inaccessible" (unusable) at runtime.
This post is what I just read.
The way he implements Singleton in C++ confuses me. I got several Questions about it and here is his code:
template<typename T>
class Singleton {
public:
static T& getInstance() { //Question 1
return instance;
}
private:
static T instance;
};
class DebugLog : public Singleton<DebugLog> { //Question 2
public:
void doNothing() {}
};
Question
I think we should put the static T& getInstance()'s definition outside of the class body, right?
He tries to make class DebugLog a singleton class, but when he inherits Singleton<DebugLog>, the DebugLog doesn't already exist, right? If right, then how can the template class Singleton instantiate an un-existent class?
1) Nope, it doesn't matter how you structure your code. Singleton isn't a class, by the way: It's a template. Since the full template definition must be visitible at any instantiation site anyway, you might as well define everything inline.
2) class DebugLog : public Singleton<DebugLog> is fine. We are not inheriting from a non-existing class; rather, we are inheriting from the class Singleton<DebugLog>. Templates can be instantiated on incomplete types. (There are several rules what you can and cannot do with such a type parameter.)
For example, template <typename T> class Foo { }; can certainly be instantiated on any type without problem. More interestingly, template <typename T> struct PointerFactory { typedef T * type; }; can be instantiated on any type, complete or not. In the present situation, the purpose of the template parameter in the CRTP is solely to inform the base class of its eventual derived type, so this is entirely fine.
It would certainly be cleaner if the function were defined outside of
the class, and make the code easier to read and to maintain. In this
case, however, the complete class is small enough that the difference
isn't very great, and of course, because we're dealing with a template,
the actual definition still has to be included in every translation unit
which uses it.
The C++ standard doesn't speak of “existence” with regards to classes (or anything
else). At the point of template instantiation, name lookup finds
DebugLog, and finds that it is a class (thus, a type). At that point,
it is an incomplete type, and there are only limited things you can do
with an incomplete type. If the class template which is instantiated
doesn't do anything that requires a complete type (and Singleton
doesn't), then there is no problem. (Note that only the class
definition is instantiated at this point; class member functions will
not be instantiated until they are used.)
I might add that there is still one important thing missing from the
code you posted: there is no definition for the declaration
Singleton::instance. You still need to add a:
template<typename T> T Singleton<T>::instance;
somewhere.
You must use a pointer to T in this case:
template<typename T>
class Singleton {
public:
static T& getInstance() {
static T * instance = NULL;
if (!instance)
instance = new T;
return *instance;
}
};
class DebugLog : public Singleton<DebugLog> { //Question 2
public:
void doNothing() {}
};