I'm trying to create the program that executes some code only if the template is instantiated (it will be used for low-level driver initialization). Now I have the following solution.
class Initializer
{
public:
Initializer(){
// This code is executed once
}
void silly() const{
}
};
template <class T>
class Proxy{
protected:
static const Initializer init;
};
template<class T>
const Initializer Proxy<T>::init;
template<class T>
class MyTemplate : public Proxy<void>{
public:
static void myMethod1(){
init.silly();
// ... Something useful
}
static void myMethod2(){
init.silly();
// ... Something useful
}
};
The Initializer
default constructor is executed only in case I call myMethod1()
or myMethod2()
somewhere.
But is there a way to get rid of those init.silly();
lines?
Your problem, is that members of a template are not instantiated unless they are referenced.
Rather than calling init.silly()
, you can just reference the member:
static void myMethod1(){
(void)init;
// ... Something useful
}
Or, if you want init
to be defined absolutely always, you can explicitly instantiate it:
template<>
const Initializer Proxy<void>::init{};
template and low-level driver initialization?.. I'd try to make it as C as possible :) to ensure exact behavior.
You can do something like this perhaps:
class Initializer
{
public:
Initializer() {
// This code is executed once
}
};
template <class T>
class Proxy {
protected:
Proxy()
{
static Initializer init;
}
};
template<class T>
class MyTemplate : public Proxy<void> {
public:
void myMethod1() {
// ... Something useful
}
void myMethod2() {
// ... Something useful
}
};
All your code uses only static functions and doesn't really show why you would use classes and templates. With my change I made myMethod1
and myMethod2
non static and Proxy() constructor would create Initializer
once.
Note that because of all that template mess your Initializer
might be executed as many times as you instantiate Proxy template. Did you really mean it? If not, convert to clear readable code that doesn't have this unexpected results. This will also be better maintainable and readable for others:
class Initializer
{
Initializer() {
// This code is executed once
}
public:
void init()
{
static Initializer init;
}
};
template<class T>
class MyTemplate {
public:
static void myMethod1() {
Initializer::init();
// ... Something useful
}
static void myMethod2() {
Initializer::init();
// ... Something useful
}
};
This makes it absolutely clear that Initializer
will be created only once just before myMethod1
or myMethod2
is called. If nothing calls your Initializer::init
then that code from Initializer
should be removed at link time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With