Force template static member instantiation - c++

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.

Related

Way to call a static method of a class template without specifying an instantiation?

Is there any way to define a static method in a class template which can be then be called without specifying the instantiation?
I think this could be useful in cases where you have some auxiliary static function, which logically belongs in a class (which happens to be a template one), but doesn't depend on the template parameter.
I don't mind either:
Having the same static method (including address and all) for all
instantiations, or
Having a separate static method for each instantiation, but be able to call the static method without
specifying an instantiation where I call the method (some default
would be called).
e.g.
template<typename T> class C {
public:
static int func() { return 0; }
};
int main()
{
// This works.
return C<int>::func();
// These don't work.
// return C<>::func();
// return C::func();
}
The simplest solution is probably to have the static function belong in a base class, and then the template derives from the base:
struct CBase {
static int func() { return 0; }
};
template<typename T> class C : public CBase {
public:
};
int main()
{
// This works.
return C<int>::func();
// This will work too:
return CBase::func();
}
You can use inheritance which will also remove the duplication of any non static functions ( that also don't care about the template type ) in your binary, i.e:
class A {
public:
static int func() { return 0; }
};
template<typename T>
class B : A {
};
If you want to get C or C<> to work you can either rely on a base non-template class that contains the given function or use template specializations as it follows:
template<typename...>
struct C;
template<>
struct C<> {
static int func() { return 0; }
};
template<typename T>
struct C<T>: C<> {
// all the other things around...
};
int main() {
C<int>::func();
C<>::func();
}
For you don't provide a definition for the primary template, accepted specializations are:
C<> that contains only the given function
C<T> that accepts only a parameter as it was in the original example
See it on wandbox.
If you can't use variadic templates, you can still do something similar with a custom type.
As an example:
struct func_only {};
template<typename T = func_only>
struct C;
template<>
struct C<func_only> {
static int func() { return 0; }
};
template<typename T>
struct C: C<func_only> {
// all the other things around...
};
int main() {
C<int>::func();
C<>::func();
}
That being said, make it a free function looks to me as the best solution anyway.
How would that work? You typically depend on the type in your static functions too.
template<typename T> class C {
public:
static int func() { return sizeof(T); }
};
If they do not depend on it, you should probably make them free functions, or static members of a base class of this class.

Template class, static function call -> is this elegant?

I have a template class with all functions declared as static.
template <class T>
class Cache {
private:
Cache() {}
static std::map<std::string, std::string> c_files;
public:
~Cache() {}
template<class T> static void add(T const &file, std::string id) {
return;
}
//... here are some other functions
static void init() {
// do some initialization
}
}
Normally I would call it like:
Cache<BITMAP*>::add(my_bitmap, "my_identifier");
which works fine.
But the thing is, I need to do some one-time initialization when my app starts. (checking for cached files on the HDD, push them into the map).
At the moment I'm using a "fake" call like:
Cache<bool>::update();
which I think is really a mess.
Now, is this messy call okay, or is it complete against some programming standards? How would you solve that problem?

Template function having its caller's context?

Consider the following code snippet.
template <T>
MyPtr<T> CreateObject()
{
// Do something here first...
// return our new object
return MyPtr<T>(new T());
}
class Foo
{
private:
Foo() { }
public:
static MyPtr<Foo> GetNewInstance()
{
// ERROR: Foo is private...
return CreateObject<Foo>();
}
};
class Bar
{
public:
Bar() { }
};
int main()
{
MyPtr<Bar> bar = CreateObject<Bar>();
return 0;
}
Without resorting to macro for CreateObject (I like the syntax of MyPtr<type> obj = CreateObject<type>(params)), is there a way to make the function CreateObject share the same context as the caller function, thus able to access private Foo c'tor? 'friend' is not what I'm looking for as it would mean anyone calling CreateObject would have access to private Foo c'tor, which is not what I want. Overloading the new operator wouldn't work either as it is imperative that a MyPtr is returned instead of just T* (by assigning T* to MyPtr assigns a type to the object that is required somewhere else).
I guess what I'm looking for is something in between a macro and a template function (syntax of a template function but gets expanded fully like a macro). It would be quite useful to have this feature in this particular case.
Well, you could do that with the passkey pattern:
template<class T, class PassKey>
MyPtr<T> CreateObject(PassKey const& key)
{
return new T(key);
}
class FooKey{
private:
FooKey(){} // private ctor
FooKey(const FooKey&); // undefined private copy ctor
friend class Foo;
};
class Foo{
public:
// public ctor
Foo(FooKey const&){}
static MyPtr<Foo> GetNewInstance()
{
return CreateObject<Foo>(FooKey());
}
};
Example at Ideone.
With C++0x, this can be done much easier than creating a new Key struct every time, since template parameters are now allowed to be friends:
template<class T>
struct PassKey{
private:
PassKey(){}
PassKey(const PassKey<T>&);
friend T;
};
This is basically the same as attempting to use make_shared with a private constructor.
The only way to allow this is with friend. You're pretty much stuck in this case I'm afraid.
I am not sure as to what you are trying to achieve. The simplification to post the problem here has taken away the actual need for the whole thing. So I will just assume that you know what you are doing, and that you really need this (and I suggest that you rethink whether you do need it, as I don't see a point...)
At any rate, you can solve the problem by passing a creator callback to the CreateObject template:
template <typename T, typename Creator>
MyPtr<T> CreateObject( Creator creator )
{
// Do something here first...
return MyPtr<T>(creator());
}
class Foo
{
private:
Foo() {}
static Foo* create() { return new Foo(); }
public:
static MyPtr<Foo> GetNewInstance() {
return CreateObject<Foo>( &Foo:create );
}
// ...
};
The actual issue though, is what does Do something here first actually does that forces you into this complex creation patterns. The fact that it has to be executed before the creation of the new object seems to indicate that there are hidden dependencies not shown in the code, and that usually end up in maintenance nightmares, where someone down the line reorders some code, or adds a new constructor and everything seems to fall apart. Revisit your design and consider whether those dependencies can be simplified or made explicit.
Since you are newing up the object in the very end it really doesn't relate to your CreateObject function. So Change the function prototype to:
template <typename T>
MyPtr<T> CreateObject(T* const p)
{
//...
return MyPtr<T>(p);
}
Usage:
static MyPtr<Foo> GetNewInstance()
{
return CreateObject(new Foo());
}
is there a way to make the function CreateObject share the same context as the caller function
Yes, pass the context you need as an argument (either as an argument to the template, or as an argument to the function).
In practice, move the new T call to a separate function (or struct template, as I chose to do here), like this:
// Dummy representation of your pointer type
template <typename T>
struct MyPtr
{
MyPtr( T *p ) { }
};
// Default constructor template; may be specialized to not use "new" or so.
template <typename T>
struct Constructor
{
static T *invoke() { return new T; }
};
// Needs to be a struct (or class) so 'C' can have a default value
template <typename T, typename C = Constructor<T> >
struct CreateObject
{
MyPtr<T> operator()() {
return MyPtr<T>( C::invoke() );
}
};
class Foo
{
private:
friend struct Constructor<Foo>;
Foo() { }
public:
static MyPtr<Foo> GetNewInstance()
{
return CreateObject<Foo>()();
}
};
If you want to handle different constructor signatures (read: if not all types T have the same constructor signature), you could also choose to not pass the Constructor as a template to the CreateObject struct, but instead use a function argument. That way, you could 'load' a Constructor like this:
// ...
static MyPtr<Foo> GetNewInstance()
{
Constructor<Foo> c( arg1, arg2, arg3 );
return CreateObject<Foo>( c );
}

c++ template problem

i have a class which has a template by other purposes:
template<class t>
class MyClass {
public: //of course public...
t foo;
std::string text;
}
and i have another class which method get all kind of these class through the arguments, and want to store the pointer in an array. The class dont want to access the specific (tempalted) parts of the classes only the common attributes/methods.
class Container {
public: //of course public...
MyClass* array; //this is allocated with some magic.
void bar(MyClass& m) {
and want to store the class in a MyClass* array.
}
}
here is the error that argument list for template missing
how can i solve this?
The simplest method would be to make that function a template as well:
template <class t>
void bar(MyClass<t>& m) {
// ...
}
Note that that should probably be const MyClass<t>&, because you don't need to modify it.
Your new code is meaningless. There is no such that as an object of type MyClass, because MyClass is a template. If you want to operate on these classes irrespective of their template argument, then you need to factor out the non-template portions as a base class:
class MyClassBase
{
public:
// polymorphic base classes should always have virtual destructors
~MyClassBase() {}
virtual void some_function() = 0;
};
template <typename T>
class MyClass : public MyClassBase
{
public:
// implement abstract functions
void some_function()
{
// template argument T is available here
}
};
Then you can refer to that base, and when you call a virtual function it will dynamically dispatch:
class Container
{
public:
// no magic: use a std::vector for dynamic arrays
std::vector<MyClassBase*> array; // not by value! avoid slicing
void bar(MyClassBase& m)
{
array.push_back(&m);
}
void baz()
{
array[0]->some_function(); // for example
}
};
How about putting a common base class.
class MyClassCommon {
protected:
~MyClassCommon() { }
public:
std::string text;
};
template<class t>
class MyClass : public MyClassCommon {
public: // of course public...
t foo;
};
class Container {
public: // of course public...
MyClassCommon* array; // this is allocated with some magic.
void bar(MyClassCommon& m) {
/* ... */
}
};
If you want to create a "multi-template" array, you'd better use a non-template class as a base class of a template class. Or you can make a template array and store any objects in it.
the text variable in your class is private so unless you bar function is a method of the class you can't legally use it like that

class containing a generic type of a child

Is there any possible way that a generic type can be used to contain a child of a base class.
From the assignment given to me, I am to create something similar to the following in structure.
template <class T>
class Fruit {
private:
int count;
int location_id;
T type;
public:
virtual void displayInfo();
};
class Apple : private Fruit<Apple> {
private:
int variety;
public:
void displayInfo() {
printf("Location %i has %i of %s in stock", location_id, count, variety);
}
};
Fruit<Apple> appleinventory[SIZE];
Basically, I think you can't have a template generic type be the same as a derived class. Am I wrong? Is there something similar that would possibly work?
Update:
For the assignment, I believe we are to use inheritance to show use of virtual functions. I've updated the code above. I think this would work, but does NOT need templates to be successful. We have not covered any advanced, redundant inheritance methods in class.
This is perfectly fine, in principle.
Read up about Curiously Recurring Template Pattern (CRTP) for more info on usage of derived class as the instantiating type in a class template that is its base, esp the example about static polymorphism which should look 'curiously' familiar.
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Ignoring questions of why you want to do this....you can get some of the way by doing this following:
template <class T> class Fruit
{
private:
int count;
int location_id;
T* type;
};
class Apple : private Fruit<Apple>
{
private:
int seeds;
bool red;
};
Fruit<Apple> appleinventory[SIZE];
Note the T* type is now a pointer to Apple rather than an instance of Apple.