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
Related
I faced a problem while trying to arrange my project files C++
simply I'm designing a specific template class Mystackt and I want to include entire class inside the public part of Mystackt as an iterator class MyIterator{};
I wrote all of this stuff in my header file MyTemplate.h
so briefly it will appear as following
template <class Type> /* that's in file **MyTemplate.h** */
class MyStackt
{
friend somefunction (int,string,bool);
public:
class iterator
{
public:
iterator();
void somefunc(param1,param2.....);
void otherfunc(...);
private:
Type* ptr;
};
int public_func_of_stackt(void);
void an-otherfunc(int,string,Type,...etc);
private:
int x;
string y;Type* val;
};
Now let's see he cpp file for this header MyTemplate.cpp
I can include the code for all member-functions of Mytemplate class without problems
for example :
template <class Type>
int MyStack<Type>::public_func_of_stackt(void) /*this works perfect*/
{implementation goes here ...;}
but when i am trying to write the implementation of member-functions of entire class (iterator class) the problem starts
template <class Type>
bool MyStackt<Type>::iterator somefunc(param1,param2.....)
{ return current ==rhs.current; }
the question sirs is:
how I can include my code for the member-functions of class iterator inside the Mytemplate.cpp file ?? how should i write that using that external::entire or other specific notation ?
other question :
how can i write (in Mytemplate.cpp file) the implementation for a friend function of class MyStackt ??
update#1 : thank you Veritas
but i also need to know how to define some public function of class MyStackt
if that function is returning iterator type (so it is returning an object of the entire class)
the definition will look something like that
template <class Type>
iterator Stackt<Type>::begin()
{ return *this; } /*this function did not work*/
maybe I need to use some specific notation 4 that ? what if I had a multiple nested classes
waiting for the answer from experts
thank you in advance !
You forgot the scope resolution operator when defining somefunc. The definition should be:
template <class Type>
bool MyStackt<Type>::iterator::somefunc(param1,param2.....)
{
return current == rhs.current;
}
As for the friend function, you define it like any other global function.
To your edit:
The iterator class belongs to the MyStackt's scope so whenever you need to mention it out of MyStackt you need to use the scope operator. As for your question I am not sure what you are trying to do. *this returns the instantiated object which is of type MyStackt.
Also be careful! If you want to seperate your definitions do so using .inl files or similar , not in a cpp file.
As described in the MSDN library here I wanted to experiment a bit with the pimpl idiom. Right now I have a Foo.hpp with
template<typename T>
class Foo {
public:
typedef std::shared_ptr<Foo<T>> Ptr;
Foo();
private:
class Impl;
std::unique_ptr<Impl> pImpl;
};
where the T parameter isn't used yet. The implementation is stored in Foo.cpp
template<typename T>
class Foo<T>::Impl {
public:
int m_TestVar;
};
template<typename T>
Foo<T>::Foo() : pImpl(new Impl) {
this->pImpl->m_TestVar = 0x3713;
}
Currently the compiler has two errors and one warning:
use of undefined type 'Foo<T>::Impl'; ... vc\include\memory in line 1150
can't delete an incomplete type; ... vc\include\memory in line 1151
deletion of pointer to incomplete type 'Foo<T>::Impl'; no destructor called; ... vc\include\memory in line 1152
What is the concflict here and how could I resolve it?
Edit. Removed the call to std::make_shared - copy&paste fail based on one old version.
I have had a similar issue - we've a base class in our system called NamedComponent and I wanted to create a template which takes an existing named component and converts it into a pimpl facade.
What I did was separate the template into a header and an inline file, and create a function to cause the template to be instantiated. This allows the implementation to be in a library, with the template instantiations of the facade with that implementation, and for the client to be able to use the facade based on the template and a forward declaration of the implementation.
header 'Foo.h':
template<class T> class Foo
{
public:
Foo ();
virtual ~Foo();
private:
T *impl_;
public:
// forwarding functions
void DoIt();
};
inline functions 'Foo.inl':
#include "Foo.h"
template<class T> Foo<T>::Foo() :
impl_ ( new T )
{
}
template<class T> Foo<T>::~Foo()
{
delete impl_;
}
// forwarding functions
template<class T> void Foo<T>::DoIt()
{
impl_ -> DoIt();
}
// force instantiation
template<typename T>
void InstantiateFoo()
{
Foo<T> foo;
foo.DoIt();
}
implementation cpp file - include the template inline functions, define the implementation, reference the instantiation function:
#include "Foo.inl"
class ParticularImpl {
public:
void DoIt() {
std::cout << __FUNCTION__ << std::endl;
}
};
void InstantiateParticularFoo() {
InstantiateFoo<ParticularImpl>();
}
client cpp file - include the template header, forward declare the implementation and use the pimpl facade:
#include "Foo.h"
class ParticularImpl;
int main () {
Foo<ParticularImpl> bar;
bar.DoIt();
}
You may have to fiddle with the InstantiateFoo function's contents to force the compiler to instantiate all functions - in my case, the base called all the pimpl's functions in template methods so once one was referenced, they all were. You don't need to call the Instantiate functions, just link to them.
IMHO PIMPL doesn't make much sense with templates, unless you know all possible template parameters and that set is fairly small. The problem is, that you will either have the Impl implementation in the header file otherwise, as has been noted in the comments. If the number of possible T parameters is small, you still can go with the separation, but you'll need to declare the specialisations in the header and then explicitly instantiate them in the source file.
Now to the compiler error: unique_ptr<Impl> requires the definition of Impl to be available. You'll need to directly use new and delete in the ctor Foo::Foo and dtor Foo::~Foo, respectively instead and drop the convenience/safety of smart pointers.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get “unresolved external symbol” errors when using templates?
“undefined reference” to a template class function
I got error on line: Console::getInstance()->readObjectData(a); in main.cpp
undefined reference to void Console::readObjectData<std::string>std::string&)
Console.h
http://pastebin.com/WsQR7JNq
#define CONSOLE_H
#include <string>
using namespace std;
class Console
{
public:
static Console* getInstance();
template <typename T>
void readObjectData(T& o);
protected:
private:
Console(); // Private so that it can not be called
Console(Console const&); // copy constructor is private
Console& operator=(Console const&); // assignment operator is private
static Console* m_pInstance;
};
#endif // CONSOLE_H
Console.cpp
http://pastebin.com/N02HjgBw
#include "Console.h"
#include "Log.h"
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
// Global static pointer used to ensure a single instance of the class.
Console* Console::m_pInstance = NULL;
Console::Console()
{
}
Console::Console(Console const&)
{
}
Console& Console::operator=(Console const&)
{
}
Console* Console::getInstance()
{
if (!m_pInstance) // Only allow one instance of class to be generated.
m_pInstance = new Console;
return m_pInstance;
}
template <typename T>
void Console::readObjectData(T& o) {
//cin >> o;
}
main.cpp
http://pastebin.com/U6qAJUN1
#include "Console.h"
using namespace std;
int main()
{
string a;
Console::getInstance()->readObjectData(a);
return 0;
}
any ideas?
You cannot define template<>'d function in .cpp file.
Move
template <typename T>
void Console::readObjectData(T& o) {
//cin >> o;
}
To header file.
You did not implemented this method. You have to provide implementation for your template in .h file
Because you've not put the implementation of readObjectData in the header, you will need to provide an explicit specialization of the function - one that takes std::string&.
This should go in Console.cpp:
template <>
void Console::readObjectData(string& o) {
//cin >> o;
}
You cannot place your template method implementation in Console.cpp it must appear in the header file, or you must implement an explicit specialization for std::string.
The definition for the templated function (readObjectData) has to be inlined, not in a .cpp file.
The compiler when it see's a class with a templated function, or a templated class, makes a copy of the entire class with the new type stuck in there. So if you stick the definition of the function in the .cpp file, the compiler will not know where the implementation is because it doesn't exist.
In the process of converting some C++ files to the output( executive, shared library or ... ) 2 tools will co-operate, first compiler that create object files and then linker that convert those objects to the output. What you should know is that linker has nothing to do with template( except in special case of explicit instantiation ), and templates will be instantiated by compiler and another note is compiler work with each source files and headers that included in that source file and ignore all other files of your project. So when compiler want to compile main.cpp it see no implementation of readObjectData and thus it can't generate any code in the object files for that function, and when linker want to link objects to result it will never find an implementation for that function! So the easiest way is to move your implementation of readObjectData to the .h file and every thing will work as expected.
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.
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?