So i am trying to export somethings in a project to DLL. Anyways a few of the projects use a singleton class very heavily.
template <typename T>
class DLL_IMP VA_Singleton {
protected:
VA_Singleton () {};
~VA_Singleton () {};
public:
static T *Get(){
return (static_cast<T*> (a_singleton));
}
static void Delete(){
if(a_singleton == NULL) {
delete a_singleton;
}
}
static void Create(){
a_singleton = GetInstance();
if(a_singleton == NULL){
a_singleton = new T;
}
}
private:
static T *a_singleton;
};
template <typename T> T *VA_Singleton<T>::a_singleton = NULL;
I got the export working fine, but when it comes to importing it states this:
template <typename T> T *VA_Singleton<T>::a_singleton = NULL;
Does not work with DLLImport. This is the first time ive ever really worked with DLL's in a work enviroment. Does anyone have any ideas?
Please see Multiple Singleton Instances
You will have to ensure that your template instantiation is done in one compilation unit, and you will have to move the pointer = NULL initialization to the CPP file. In other DLLs, you'll have to use extern templates.
Edit:
If you are stuck with getting templated singletons to work over multiple DLLs, you could also define a short wrapper function that returns your singleton instance so that the template instantiation is done in one compilation unit only.
Example:
template class Singleton<T>;
__declspec(dllexport/dllimport) T& getInstanceForMyType();
// in the cpp file:
T& getInstanceForMyType()
{
return Singleton<MyType>::getInstance();
}
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
I realise that there are already few topics like this on SO but I did not find any that would answer my problem.
I have already written my template singleton class using this tutorial http://www.codeproject.com/Articles/4750/Singleton-Pattern-A-review-and-analysis-of-existin
but unfortunately I keep on getting errors :
/home/USER/testcode/cpp_workshop/main.cpp:-1: error: undefined
reference to `Singleton::Instance()' :-1: error: collect2: ld
my singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
template <typename T>
class Singleton
{
public:
static T& Instance();
protected:
virtual ~Singleton();
inline explicit Singleton();
private:
static T* _instance;
static T* CreateInstance();
};
template<typename T>
T* Singleton<T>::_instance = 0;
#endif // SINGLETON_H
singleton.cpp
#include "singleton.h"
#include <cstdlib>
template <typename T>
Singleton<T>::Singleton()
{
assert(Singleton::_instance == 0);
Singleton::_instance = static_cast<T*>(this);
}
template<typename T>
T& Singleton<T>::Instance()
{
if (Singleton::_instance == 0)
{
Singleton::_instance = CreateInstance();
}
return *(Singleton::_instance);
}
template<typename T>
inline T* Singleton<T>::CreateInstance()
{
return new T();
}
template<typename T>
Singleton<T>::~Singleton()
{
if(Singleton::_instance != 0)
{
delete Singleton::_instance;
}
Singleton::_instance = 0;
}
and that's how I call it (with normall - not templated or anything - class Game )
Singleton<Game>::Instance().run();
Put your method definitions under your class definition in the header, and delete your cpp. Templated methods and methods of templated classes must be defined in headers (with a couple hackish exceptions).
Per request, here are the 'hackish exceptions':
1) See #Desmond Hume's answer
2) Only use the templated class from the cpp in which the methods are defined. For example, you can declare/define a templated class in an unnamed namespace in a cpp, that's just fine.
You could put the definition of your Singleton class into the header file or you could keep the separation of declarations (the header) and definitions (the .cpp file) as it is now if you like it better and explicitly instantiate the Singleton class with each of the types you are going to use it with. To explicitly instantiate Singleton class, try putting the following at the end of the .cpp file:
template
class Singleton<Game>;
With another type it would look in the same way:
template
class Singleton<AnotherGame>; // just for example
Its not possible to separate the definiton (header file) and implementation (cpp) of a templated class.
So you have one of two solutions:
1- implement everything in the header file .h. something like this
template <typename T>
class Singleton
{
public:
static T& Instance(){}
protected:
virtual ~Singleton(){}
inline explicit Singleton(){}
private:
static T* _instance;
static T* CreateInstance(){}
};
Another solution is to rename your .cpp class to .hpp. Don't include the .h file inside the .hpp file, but the other way around. i.e. include .hpp file inside .h file
I personally prefer the first solution
Cheers
I am trying to create a templated factory class that exports a create method:
template <typename T>
class ClassFactory
{
_declspec(dllexport) static void* Create()
{
return new T;
}
};
class Foobar : ClassFactory<Foobar>
{
std::string foo;
};
This code compiles just fine, but I don't see anything in the exports table when I look at the output of dumpbin /exports
The following code exports Create() correctly:
class ClassFactoryBase
{
_declspec(dllexport) virtual void* Create() = 0;
};
template <typename T>
class ClassFactory : ClassFactoryBase
{
void* Create()
{
return new T;
}
};
class Foobar : ClassFactory<Foobar>
{
std::string foo;
};
However, I need Create() to be static. Why does sample 2 work, while sample 1 does not? Is there a way to export a static template method?
The compiler sees that the Create() function is never called so it does not generate any code for it. To make it work you need to explicitly instantiate your template like this:
template class ClassFactory<Foobar>;
Just add this line to your source. Now the compiler will generate the code for this function and export it. For more information see this MSDN article - Explicit Instantiation (C++)
To answer your other question why the example 2 works and example 1 does not, let's take a closer look at the derived class Foobar. There is a virtual function in this class so the compiler has to generate a vtable. To fill in the vtable the compiler needs to know the address of Create() and this is when it is implicitly instantiated from the base class template. The code for this function is generated and exported to the DLL, as requested. That is why the example 2 works.
There is no way to export a template method from the DLL, because non-instanced template method is not even compiled. Your examples doesn't do much with the DLL itself, the header file is the one, who makes everything work.
Follow-up question to [Does casting to a pointer to a template instantiate that template?].
The question is just as the title says, with the rest of the question being constraints and usage examples of the class template, aswell as my tries to achieve the goal.
An important constraint: The user instantiates the template by subclassing my class template (and not through explicitly instantiating it like in my tries below). As such, it is important to me that, if possible, the user doesn't need to do any extra work. Just subclassing and it should work (the subclass actually registers itself in a dictionary already without the user doing anything other than subclassing an additional class template with CRTP and the subclass is never directly used by the user who created it). I am willing to accept answers where the user needs to do extra work however (like deriving from an additional base), if there really is no other way.
A code snippet to explain how the class template is going to be used:
// the class template in question
template<class Resource>
struct loader
{
typedef Resource res_type;
virtual res_type load(std::string const& path) const = 0;
virtual void unload(res_type const& res) const = 0;
};
template<class Resource, class Derived>
struct implement_loader
: loader<Resource>
, auto_register_in_dict<Derived>
{
};
template<class Resource>
Resource load(std::string const& path){
// error should be triggered here
check_loader_instantiated_with<Resource>();
// search through resource cache
// ...
// if not yet loaded, load from disk
// loader_dict is a mapping from strings (the file extension) to loader pointers
auto loader_dict = get_all_loaders_for<Resource>();
auto loader_it = loader_dict.find(get_extension(path))
if(loader_it != loader_dict.end())
return (*loader_it)->load(path);
// if not found, throw some exception saying that
// no loader for that specific file extension was found
}
// the above code comes from my library, the code below is from the user
struct some_loader
: the_lib::implement_loader<my_fancy_struct, some_loader>
{
// to be called during registration of the loader
static std::string extension(){ return "mfs"; }
// override the functions and load the resource
};
And now in tabular form:
User calls the_lib::load<my_fancy_struct> with a resource path
Inside the_lib::load<my_fancy_struct>, if the resource identified by the path isn't cached already, I load it from disk
The specific loader to be used in this case is created at startup time and saved in a dictionary
There is a dictionary for every resource type, and they map [file extension -> loader pointer]
If the dictionary is empty, the user either
didn't create a loader for that specific extension or
didn't create a loader for that specific resource
I only want the first case to have me throw a runtime exception
The second case should be detected at compile / link time, since it involves templates
Rationale: I'm heavily in favor of early errors and if possible I want to detect as many errors as possible before runtime, i.e. at compile and link time. Since checking if a loader for that resource exists would only involve templates, I hope it's possible to do this.
The goal in my tries: Trigger a linker error on the call to check_error<char>.
// invoke with -std=c++0x on Clang and GCC, MSVC10+ already does this implicitly
#include <type_traits>
// the second parameter is for overload resolution in the first test
// literal '0' converts to as well to 'void*' as to 'foo<T>*'
// but it converts better to 'int' than to 'long'
template<class T>
void check_error(void*, long = 0);
template<class T>
struct foo{
template<class U>
friend typename std::enable_if<
std::is_same<T,U>::value
>::type check_error(foo<T>*, int = 0){}
};
template struct foo<int>;
void test();
int main(){ test(); }
Given the above code, the following test definition does achieve the goal for MSVC, GCC 4.4.5 and GCC 4.5.1:
void test(){
check_error<int>(0, 0); // no linker error
check_error<char>(0, 0); // linker error for this call
}
However, it should not do that, as passing a null pointer does not trigger ADL. Why is ADL needed? Because the standard says so:
ยง7.3.1.2 [namespace.memdef] p3
[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup or by qualified lookup until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). [...]
Triggering ADL through a cast, as in the following definition of test, achieves the goal on Clang 3.1 and GCC 4.4.5, but GCC 4.5.1 already links fine, as does MSVC10:
void test(){
check_error<int>((foo<int>*)0);
check_error<char>((foo<char>*)0);
}
Sadly, GCC 4.5.1 and MSVC10 have the correct behaviour here, as discussed in the linked question and specifically this answer.
The compiler instatiates a template function whenever it is referenced and a full specification of the template is available. If none is available, the compiler doesn't and hopes that some other translation unit will instantiate it. The same is true for, say, the default constructor of your base class.
File header.h:
template<class T>
class Base
{
public:
Base();
};
#ifndef OMIT_CONSTR
template<class T>
Base<T>::Base() { }
#endif
File client.cc:
#include "header.h"
class MyClass : public Base<int>
{
};
int main()
{
MyClass a;
Base<double> b;
}
File check.cc:
#define OMIT_CONSTR
#include "header.h"
void checks()
{
Base<int> a;
Base<float> b;
}
Then:
$ g++ client.cc check.cc
/tmp/cc4X95rY.o: In function `checks()':
check.cc:(.text+0x1c): undefined reference to `Base<float>::Base()'
collect2: ld returned 1 exit status
EDIT:
(trying to apply this to the concrete example)
I'll call this file "loader.h":
template<class Resource>
struct loader{
typedef Resource res_type;
virtual res_type load(std::string const& path) const = 0;
virtual void unload(res_type const& res) const = 0;
loader();
};
template<class Resource>
class check_loader_instantiated_with : public loader<Resource> {
virtual Resource load(std::string const& path) const { throw 42; }
virtual void unload(Resource const& res) const { }
};
template<class Resource>
Resource load(std::string const& path){
// error should be triggered here
check_loader_instantiated_with<Resource> checker;
// ...
}
And another file, "loader_impl.h":
#include "loader.h"
template<class Resource>
loader<Resource>::loader() { }
This solution has one weak point that I know of. Each compilation unit has a choice of including either only loader.h or loader_impl.h. You can only define loaders in compilation units that include loader_impl, and in those compilation units, the error checking is disabled for all loaders.
After thinking a bit about your problem, I don't see any way to achieve this. You need a way to make the instantiation "export" something outside the template so that it can be accessed without referencing the instantiation. A friend function with ADL was a good idea, but unfortunately it was shown that for ADL to work, the template had to be instantiated. I tried to find another way to "export" something from the template, but failed to find one.
The usual solution to your problem is to have the user specializes a trait class:
template < typename Resource >
struct has_loader : boost::mpl::false_ {};
template <>
struct has_loader< my_fancy_struct > : boost::mpl::true_ {};
To hide this from the user, you could provide a macro:
#define LOADER( loaderName, resource ) \
template <> struct has_loader< resource > : boost::mpl::true_ {}; \
class loaderName \
: the_lib::loader< resource > \
, the_lib::auto_register_in_dict< loaderName >
LOADER( some_loader, my_fancy_struct )
{
public:
my_fancy_struct load( std::string const & path );
};
It is up to you to determine whether having this macro is acceptable or not.
template <class T>
class Wrapper {};
void CheckError(Wrapper<int> w);
template <class T>
class GenericCheckError
{
public:
GenericCheckError()
{
Wrapper<T> w;
CheckError(w);
}
};
int main()
{
GenericCheckError<int> g1; // this compiles fine
GenericCheckError<char> g2; // this causes a compiler error because Wrapper<char> != Wrapper<int>
return 0;
}
Edit:
Alright this is as close as I can get. If they subclass and either instantiate OR define a constructor that calls the parent's constructor, they will get a compiler error with the wrong type. Or if the child class is templatized and they subclass and instantiate with the wrong type, they will get a compiler error.
template <class T> class Wrapper {};
void CheckError(Wrapper<int> w) {}
template <class T>
class LimitedTemplateClass
{
public:
LimitedTemplateClass()
{
Wrapper<T> w;
CheckError(w);
}
};
// this causes no compiler error
class UserClass : LimitedTemplateClass<int>
{
UserClass() : LimitedTemplateClass<int>() {}
};
// this alone (no instantiation) causes a compiler error
class UserClass2 : LimitedTemplateClass<char>
{
UserClass2() : LimitedTemplateClass<char>() {}
};
// this causes no compiler error (until instantiation with wrong type)
template <class T>
class UserClass3 : LimitedTemplateClass<T>
{
};
int main()
{
UserClass u1; // this is fine
UserClass2 u2; // this obviously won't work because this one errors after subclass declaration
UserClass3<int> u3; // this is fine as it has the right type
UserClass3<char> u4; // this one throws a compiler error
return 0;
}
Obviously you can add other accepted types by defining additional CheckError functions with those types.
Suppose I have such a template class:
template <class T>
class Queue
{
public:
static int Size;
};
template <class T> int Queue<T>::Size = 0;
And I export a function in D.dll use Queue as an parameter:
void ChangeQueueSize(Queue<int>& q)
{
q.Size = 100;
}
And then I use this exported function in an A.exe:
Queue<int> q;
q.Size = 10;
ChangeQueueSize(q);
int updatedSize = q.Size;
Since the Queue class is generated from the class template in 2 projects, there are actually 2 copies of the code, as well as the static data member.
So calling ChangeQueueSize won't really change queue size here, it just update another class's static member, which happens to be have the same class name.
What can we do to solve this problem?
Is weak symbol in gcc capable of address this?
Thanks so much.
You cannot put templates in a library in the way you might think. You can only put actual, instantiated class definitions in a library.
Templates are essentially a code generation tool, and you can only put generated code into the library.
You might want to use explicit template instantiation to make the compiler generate the code, and take the static member definition out of the header:
// Header, shipped to clients
template <class T>
class Queue
{
public:
static int Size;
};
// Library source code:
template <typename T> int Queue<T>::size = 0;
template class Queue<int>;
Now compile the source file into the library; this will contain the instance of the static member variable Queue<int>::size.
Note that your consumers will only be able to use instances of your class with T = int since they don't have access to the static member otherwise (i.e. they'd have to provide their own).
I have a singleton library from a linux project that I'm trying to port to Windows. When I try to compile, it errors with
syntax error: identifier "rpSingleton"
The error is from the following section of code:
template <typename T> inline T&
Q::Singleton<T>::Instance()
{
Singleton<T>*& rp_singleton(rpSingleton()); //ERRORS HERE
if (0 == rp_singleton)
{
rp_singleton = new Singleton<T>;
}
return rp_singleton->mInstance;
}
Below is the whole file for reference.
Any idea what's wrong?
#ifndef Q_SINGLETON_H
#define Q_SINGLETON_H
// SYSTEM INCLUDES
#include <boost/noncopyable.hpp>
// PROJECT INCLUDES
// LOCAL INCLUDES
#include "NonDerivable.h"
// NAMESPACES
namespace Q
{
template <typename T> class Singleton;
}
// FORWARD REFERENCES
namespace Q
{
template <typename T> void InstanceCleanup();
}
template <typename T> class Q::Singleton
: private boost::noncopyable
, private virtual Qf::NonDerivable
{
// FRIENDS
// Allow only T specialization of Instance be a friend
friend T& Instance<T>();
// Allow only the T specialization of Instance be a friend
friend void InstanceCleanup<T>();
public:
protected:
private:
/// The single object
T mInstance;
/// Wrapper method of a static pointer to support instance and clean up
///
static Singleton<T>*& rpSingleton();
/// Constructor is private, must use Instance Method to use the object
///
Singleton();
/// Get the Instance of the Singleton
/// \return The Instance
static T& Instance();
/// A way to free this singleton's resources before program termination
///
static void CleanUp();
};
// INLINE METHODS
template <typename T> inline T&
Q::Singleton<T>::Instance()
{
Singleton<T>*& rp_singleton(rpSingleton());
if (0 == rp_singleton)
{
rp_singleton = new Singleton<T>;
}
return rp_singleton->mInstance;
}
template <typename T> inline void
Q::Singleton<T>::CleanUp()
{
delete rpSingleton();
rpSingleton() = 0;
}
template <typename T> inline Q::Singleton<T>*&
Q::Singleton<T>::rpSingleton()
{
static Singleton<T>* sp_singleton(0);
return sp_singleton;
}
template <typename T> inline Q::Singleton<T>::Singleton()
{
}
template <typename T> inline T& Q::Instance()
{
return Singleton<T>::Instance();
}
template <typename T> inline void Q::InstanceCleanup()
{
Singleton<T>::CleanUp();
}
// NON-INLINE METHODS (TEMPLATE CLASSES ONLY!!!!)
#endif // SINGLETON_H
I think you're running into this from the C++ FAQ Lite. Basically, you're not actually initializing it. Personally, I'm surprised that the line in question is even LEGAL at all (my brain is melting at the reference-to-pointer), but take a look at the link. It shows how a compiler can interpret (or mis-interpret) certain kinds of initialization statements.
I THINK what you want to do is something like below:
Singleton<T>*& rp_singleton = rpSingleton();
So read the link. Basically I think the compiler is thinking you're calling a function, or something. Either way, the line about fixes it... I think.
Edit: you may also want to take a look at this section that deals with references.
Changing it to this:
Singleton<T>*& rp_singleton = rpSingleton();
Fixes it.
But does that make any sense?