I have a problem regarding 'static const' member initialization. In a templated class I define a const member and initialize it outside the class.
When I include the .h file where this class is implemented in multiple .cpp files, I get an LNK2005 error (I'm using VS2010) that says the constant is already defined.
// List.hpp
template <class T>
class List {
static const double TRIM_THRESHOLD;
};
template <class T>
const double List<T>::TRIM_THRESHOLD = 0.8;
I tried putting the member initialization in a .cpp file, but then I get a linker error saying that the constant is not defined at all. If the list is not templated and I put the initialization in a .cpp file, all is fine.
Is there any solution for this situation? I have #ifdef/define clauses around the file already, and it's definitely not a solution.
You should define the constant in a source file not a header (so it only gets defined once) since this is a template which you need to keep in the header(and all instances have the same value) you can use a common base class.
class ListBase {
protected:
ListBase() {} // use only as base
~ListBase() { } // prevent deletion from outside
static const double TRIM_THRESHOLD;
};
template <class T>
class List : ListBase {
};
// in source file
double ListBase::TRIM_THRESHOLD = 0.8;
Another option is to have it as a static function:
static double trim_threashold() { return 0.8; }
Edit: If your compiler supports C++11 you make your static method a constexpr function so that it has all the optimization opportunities that using the value directly has.
Related
I'm trying to build a wrapper around a managed class so I can call it from native code.
Here is the managed function :
void MyManagedFunction(MyStruct iStruct)
{
// Code according to what are the types of the 2 MyStruct members
}
struct MyStruct
{
public MyStruct(Object iValue1, Object iValue2) : this()
{
Value1 = iValue1; // Often contains DateTime::Now
Value2 = iValue2;
}
public Object Value1;
public Object Value2;
}
In my case, Value1 will almost always be System::DateTime::Now and the Value2 will almost always be a common data type (int, double, float, string, bool). I thought of making two templated function in the wrapper.
In the wrapper's .h I have the following :
#ifdef MYWRAPPER_EXPORTS
# define MYWRAPPER __declspec(dllexport)
#else
# define MYWRAPPER __declspec(dllimport)
#endif
class MYWRAPPER MyWrapper
{
public:
MyWrapper();
~MyWrapper();
template <class T> void MyNativeFunction(T iParam1)
{
MyStruct^ wStruct = gcnew MyStruct(System::DateTime::Now, iParam1);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
template <class T, class W> void MyNativeFunction(T iParam1, W iParam2)
{
MyStruct^ wStruct = gcnew MyStruct(iParam1, iParam2);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
};
This wrapper compiled without problem. The problem obviously occurred when I included the .h in the purely native code. Since I can't hide the content of the templated function, I have managed stuff visible on the native side which prevent the native code from compiling.
I was wondering if there was a workaround in order to achieve this. I don't mind if I'm limited into using only primitive types as parameters for the function. The best thing is if I was able to simply hide the content of the templated function in the native code so it only knows about the signature
Here's what I've tried/considered so far :
Converting the parameters to void* and call a function in which would call the managed one. By doing so, I can't cast the void* back to an object since I lose its type and using typeid to get the 'T' or 'W' type doesn't help since it vary from a compiler to another.
Overloading the function for every types I want to use. This is what I'll most likely use if I doesn't find a better solution. The problem is it means alot of overloading (especially for the 2 parameters function considering the number of combination)
If you know all the types your template will take, you can force instantiate it with those variables and thus put the code for the template functions in the source file instead of a header.
You can look at the example provided in Storing C++ template function definitions in a .CPP file
As he says you can do as below (copy-paste alert):
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
.cpp file
template <typename T>
void foo::do(const T& t)
{
// Do something with t
}
template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);
I have the following method declared in the public area of a class like that:
In the header file:
class EntityManager
{
public:
...
template <typename ComponentType>
bool addComponentToEntity(const Entity in_Entity, const shared_ptr<ComponentType> in_ComponentInstance);
...
}
In the source file:
template <typename ComponentType>
bool EntityManager::addComponentToEntity(const Entity in_Entity, const shared_ptr<ComponentType> in_ComponentInstance)
{
...
}
Then I try to use it like this:
Entity l_Entity = 1;
shared_ptr<TestComponent> l_TestComponent(new TestComponent());
EntityManager* l_EntityManager = new EntityManager();
l_EntityManager->addComponentToEntity<TestComponent>(l_Entity, l_TestComponent);
This results in the compiler complaining:
undefined reference to `bool EntityManager::addComponentToEntity<TestComponent>(unsigned long, boost::shared_ptr<TestComponent>)'|
I am aware that this is probably because I am not very experienced in C++ programming, but I can't see a reason why the function is undefined. I ommitted some other code that calls other functions of the EntityManager class and that works perfectly well.
I also tried rewriting the function with regular pointers, references and even passes by value with the same result.
Template methods/functions must be defined in the header itself (unless the method's class itself is defined in a source file). This is also the case for all methods of a template class (even if the methods themselves aren't template methods).
Most people don't even bother defining them below the class definition, they just define them inline inside the class:
class EntityManager
{
public:
...
template <typename ComponentType>
bool addComponentToEntity(const Entity in_Entity, const shared_ptr<ComponentType> in_ComponentInstance)
{
...
}
...
}
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 initialize a static object without success. The purpose is to automatically register a factory class in a repository (which is a singleton).
I've already had a look at: How to force a static member to be initialized?
One of the comments says that (there is also an example that I've followed):
I read it up in the C++ standard (14.7.1): Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
So I'm trying to do something similar but I haven't manage to force the object initialization. Here is the code. I don't know what I'm missing. This is the template I'm using.
namespace my_lib
{
template <typename T>
struct FactoryHelper
{
FactoryHelper ();
static FactoryHelper<T> _helper;
};
}
And this is the macro that the user of the library would use to define the factory class and, at the same time, register an object in the repository:
#define CREATE_FACTORY(ClassName)\
namespace my_lib\
{\
class ClassName##Factory;\
template<> FactoryHelper<ClassName##Factory>::FactoryHelper () { std::cout << "object initialized!" << std::endl; }\
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper;\
struct ClassName##Factory : public FactoryBase<ClassName> {\
...\
};\
}
The previous code is defined in a header file (Factory.h).
In a .cpp file (Example.cpp), I have:
CREATE_FACTORY(UnitTestExample)
...
When I execute the program, I cannot see the message that the constructor prints when it is invoked. Any help is more than welcome.
Thanks in advance.
This is a tricky area of C++. What you've done is to try to define the static member here:
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper;\
but this is actually a declaration and not a definition. For C++ to treat it as a definition you have to pass something to the constructor. Typically, this is the value you want to initialize it to:
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper = FactoryHelper<ClassName##Factory>();\
But in your case, you want this to be a singleton, so you probably don't want it to be copyable. In that case, you need some dummy parameter:
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper(0);\
and you have to modify your constructor appropriately:
template<> FactoryHelper<ClassName##Factory>::FactoryHelper (int) { std::cout << "object initialized!" << std::endl; }\
Here is the complete working example:
#include <iostream>
namespace my_lib
{
template<typename> struct FactoryBase { };
template <typename T>
struct FactoryHelper
{
FactoryHelper (int);
static FactoryHelper<T> _helper;
};
}
#define CREATE_FACTORY(ClassName)\
namespace my_lib\
{\
class ClassName##Factory;\
template<> FactoryHelper<ClassName##Factory>::FactoryHelper (int) { std::cout << "object initialized!" << std::endl; }\
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper(0);\
struct ClassName##Factory : public FactoryBase<ClassName> {\
};\
}
struct UnitTestExample {
};
CREATE_FACTORY(UnitTestExample);
int main(int argc,char **argv)
{
return 0;
}
That said, using some of the suggestions in the other answers may be a better design decision.
More information on the explicit specialization declaration vs. definition can be found here: static member initialization for specialized template class
What your macro does is to declare a specializations of some members of a class. This won't create any object and probably not what you really want anyway. What you'd need is a definition of FactoryHelper<SomeClass>::_helper somewhere. A definition of the static member would look something like this:
FactoryHelper<foo> FactoryHelper<foo>::_helper;
That said, I don't think the is the the way to go at all: all you really need is to instantiate something which registers a factory function and this can be done much simpler and, especially, without macros.
Here is how I would do this:
template <typename T>
struct factory_helper
{
std::auto_ptr<base> create_fuction() { return std::auto_ptr<base>(new T()); }
factory_helper(std::string const& name) {
factory.register_class(name, create_function);
}
};
This assumes that you want to create objects derived from type base and that your factory uses a mapping to function object returning std::auto_ptr<base> as constructor functions and that it has a register_class() function which takes the name and the constructor function as parameters. Neither of these assumptions is inherent to the apprach, though: this is just to fill in some of the blanks you didn't mention. You would register a factory function for a class foo something like this:
static factor_helper<foo> foo_helper("foo");
Instead of a static member (you have to create somewhere), consider the possibility of a static variable into a static function, like
namespace my_lib
{
template <typename T>
struct FactoryHelper
{
FactoryHelper () { ... };
static FactoryHelper<T>& helper()
{ static FactoryHelper<T> h; return h; }
};
}
Not the same as you are asking, but no need of out-of-band initializations.
Well, first of all thanks a lot for both the suggestions and the explanations. I added the solutions you gave me to the code and didn't work. Then I tried your solutions as stand-alone programs and worked.
The difference is that the classes I'm implementing are compiled and then linked to the executable as a static libraries. If I compile the code all together (without using static libraries) then it works.
I found the response here: Static initialization and destruction of a static library's globals not happening with g++
The .o files are not linked unless they are referenced from the main application. I have used the ld option -Wl,--whole-archive and now it works.
-Wl,--whole-archive -lmy_static_library ... -Wl,--no-whole-archive
Related to the second question, I still don't understand why I have to specify a dummy parameter in the constructor.
template<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper(0);\
Rather than doing this:
emplate<> FactoryHelper<ClassName##Factory> FactoryHelper<ClassName##Factory>::_helper = FactoryHelper<ClassName##Factory>();\
Thanks!
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).