Creating template classes in a Class Library project C++ - c++

I have a C++ class library project that is commonly used by other C++ projects. To be able to use classes inside my class library project, I wrote a header file like the example given below
#pragma once
#ifdef MYLIB
# define MYLIB_EXPORT __declspec(dllexport)
#else
# define MYLIB_EXPORT __declspec(dllimport)
#endif
No problem until I want to create a template class inside my class library project. The problem is I can't export my template class.
MyClass.h
template<class T>
class MYLIB_EXPORT MyClass
{
void myMethod();
// ...
}
template<class T>
void MyClass::myMethod()
{
// ...
}
In this case I am getting compilaton errors saying "definition of dllimport function not allowed". I know what causes the problem and I understand it. Other projects using my class library project converts the MYLIB_EXPORT keyword to __declspec(dllimport). Therefore, they are expecting the methods of MyClass to be defined in a DLL. But, then the compiler sees the definition inside the header.
How can I overcome this situation and be able to export my template classes that are defined inside my class library project?

Uninstantiated templates can't be compiled directly - they are code generators, so they are actually translated to binary instructions only when they are instantiated; for this reason, you can't export a template "in binary form" as if it was a "regular" function/class (on the other hand, at least in theory you could export an instantiation of a template).
Long story short: just leave the templates in a header to be included by library clients.
Notice that this is the exact reason why you keep templates in headers and you don't normally separate their implementation in .cpp files.

Just remove the MYLIB_EXPORT statement on template class. Then you can define class functions outside the class (but still in *.h or *.hpp header files).
MyClass.h
template <typename T>
class MyClass // MYLIB_EXPORT removed
{
void myMethod();
// ...
};
template <typename T>
void MyClass<T>::myMethod()
{
// ...
}
I got this issue. After a long time, I realized removing MYLIB_EXPORT fixed it. Hope this answer will save time to others :-)

Related

Exporting C++ template class [duplicate]

I have a dll that contains a templated class. Is there a way to export it without explicit specification?
Since the code for templates is usually in headers, you don't need to export the functions at all. That is, the library that is using the dll can instantiate the template.
This is the only way to give users the freedom to use any type with the template, but in a sense it's working against the way dlls are supposed to work.
Are you looking into exporting an instantiation of a template class through a dll? A class along the lines:
typedef std::vector<int> IntVec;
There is some discussion how to do this on:
http://support.microsoft.com/kb/168958
Another approach is to explicitly exporting each function you are interested in through a wrapper class working against this template instance. Then you won't clutter the dll with more symbols than you are actually interested in using.
When the compiler finds an instantiation of a template class, like MyTemplate<int>, then it generates the code for the template specialization.
For this reason, all the template code must be placed in an header file and included where you want to use it.
If you want to 'export' your template class, just place your code in an header file and include it where it's needed.
In your export control file.
#ifdef XXXX_BUILD
#define XXXX_EXPORT __declspec(dllexport)
#define XXXX_EXTERN
#else
#define XXXX_EXPORT __declspec(dllimport)
#define XXXX_EXTERN extern
#endif
where XXXX_BUILD is a symbol defined in your project.
To get your class exported.
XXXX_EXTERN template class XXXX_EXPORT YourClass<double>;
Where double is the type you want to instantiate the class with.
https://support.microsoft.com/en-us/help/168958/how-to-export-an-instantiation-of-a-standard-template-library-stl-clas

C++ Overloaded operator is not exported to dll [duplicate]

I have a dll that contains a templated class. Is there a way to export it without explicit specification?
Since the code for templates is usually in headers, you don't need to export the functions at all. That is, the library that is using the dll can instantiate the template.
This is the only way to give users the freedom to use any type with the template, but in a sense it's working against the way dlls are supposed to work.
Are you looking into exporting an instantiation of a template class through a dll? A class along the lines:
typedef std::vector<int> IntVec;
There is some discussion how to do this on:
http://support.microsoft.com/kb/168958
Another approach is to explicitly exporting each function you are interested in through a wrapper class working against this template instance. Then you won't clutter the dll with more symbols than you are actually interested in using.
When the compiler finds an instantiation of a template class, like MyTemplate<int>, then it generates the code for the template specialization.
For this reason, all the template code must be placed in an header file and included where you want to use it.
If you want to 'export' your template class, just place your code in an header file and include it where it's needed.
In your export control file.
#ifdef XXXX_BUILD
#define XXXX_EXPORT __declspec(dllexport)
#define XXXX_EXTERN
#else
#define XXXX_EXPORT __declspec(dllimport)
#define XXXX_EXTERN extern
#endif
where XXXX_BUILD is a symbol defined in your project.
To get your class exported.
XXXX_EXTERN template class XXXX_EXPORT YourClass<double>;
Where double is the type you want to instantiate the class with.
https://support.microsoft.com/en-us/help/168958/how-to-export-an-instantiation-of-a-standard-template-library-stl-clas

recommendations for implementation of C++ template class in a separate file and IDE support

Template class implementation needs to be accessible when the template is instantiated in the calling code. Hence the easy solution is to put the class definition and implementation in a single header file.
There are of course other solutions. The solutions I could find with Google are basically already summarized in http://blog.ethanlim.net/2014/07/separate-c-template-headers-h-and.html
which proposes either:
All implementation into the header file
Explicit Template Instantiation in the implementation (*.cpp)
A variant of the first I have seen other persons use and I have used myself is to create a header file for the implementation myTemplateClass_impl.h that is included from the other header myTemplateClass.h.
I always thought it was the recommended way of doing this but searching with Google, I was surprised I could not find this technique described anywhere. Now I have one problem with this technique: it breaks vscode intellisense (or other IDEs C++ support) because the myTemplateClass_impl.h is not self contained.
Now there is a way to make it IDE friendly but it is a bit convoluted:
myTemplateClass.h
#ifndef MYTMPCL_H
#define MYTMPCL_H
namespace tmpcl {
template <typename T> class TmpCL
{
...
}
} // namespace tmpcl
#include "myTemplateClass_impl.h"
#endif // MYTMPCL_H
myTemplateClass_impl.h
#ifndef MYTMPCL_IMPL_H
#define MYTMPCL_IMPL_H
#include "myTemplateClass.h"
namespace tmpcl {
// implementation
template <typename T> TmpCL::...
} // namespace tmpcl
#endif // MYTMPCL_IMPL_H
Now it does not matter which of the two files is included. They both expand to the same code and vscode intellisense is happy.
Is this design any good?
Thank you.
Also I was surprised I could not find recommendations for how to do this in the C++ core guidelines at https://isocpp.org/

Multiple-File Template Implementation

With normal functions, the declaration and definition are often separated across multiple files like so:
// Foo.h
namespace Foo
{
void Bar();
}
.
// Foo.cpp
#include "Foo.h"
void Foo::Bar()
{
cout << "Inside function." << endl;
}
It is my understanding that this cannot be done with templates. The declaration and definition must not be separate because the appropriate form of the template is created "on-demand" when needed.
So, how and where are templates typically defined in a multiple-file project like this? My intuition is that it would be in Foo.cpp because that's where the "meat" of functions normally is, but on the other hand it's the header file that's going to be included.
You need to write definitions of templated methods in a .hxx file and include it at the end of your header file (.hh) in which you declare it. The .cc/.cpp is used to define non-templated methods.
So you'll have one .hh, one .hxx (included at the end of the .hh), and one .cc; so that including your templated class header file will include its definition too.
Example:
// list.hh
#IFNDEF LIST_HH
# DEFINE LIST_HH
template <typename T>
class List
{
void fun1(T a);
void fun2();
}
# include "list.hxx"
#ENDIF
// list.hxx
#IFNDEF LIST_HXX
# DEFINE LIST_HXX
# include "list.hh"
template <typename T>
void List::fun1(T a)
{
// ...
}
#ENDIF
// list.cc
#include "list.hh"
void List::fun2()
{
// ...
}
// anywhere.cc
#include "list.hh"
// ...
EDIT
There are several strategies to compile templates. The most common strategy is the one described above to let every user of the class template instantiate the code.
But, because the *.hh file includes the *.hxx file, each time a simple declaration of a template is needed, the full implementation comes with it. And if the implementation requires other declarations such as std::string, you force all the client code to parse the string header.
To avoid instantiations several times (time and space consuming), you can introduce a fourth type of file, *.hcc: files that must be compiled once for each concrete template parameter.
See Also Compile-Time Dependencies
EDIT2
Writing the template definition directly in the header file is called inclusion model. Doing so increases the cost of including the header. Not only because we added the definition of the template but because we included headers (, , whatever) which represent thousands of lines. A real problem for significant programs to compile (we are talking about hours of compilation here).
The separation model
Source
And my last argument: keep clear the header file so that it only contains the class declaration and its documentation. Like that, any other programmer is able to fastly read your header file: what is the public interface of this class, what does the documentation says.
Template code stays in the .hh file. There's no reason to make them separate files, though it is good practice to put the definitions after all the declarations.
When the compiler generates template code, it flags it so that the linker knows that the instantiation of a template in one compilation unit (i.e. .o file) is the exact same code as one in another unit. It will keep one and discard the rest, rather than bailing out with a "multiply defined symbol" error.
This is true of modern compilers with good template support. In the case of GCC, since 2.8. (I know, I wrote a lot of code for gcc 2.7.2.2 before they smartened the linker up and you had to jump through hoops to make templates build right.)
I'm disappointed that no answers mentioned that the C++ standard permits you to separate the definition from the declaration. It goes like this:
// Foo.h
export template<class T> T f();
// Foo.cpp
#include "Foo.h"
export template<class T> T f()
{
// blah blah
}
Unfortunately, almost no compilers support export. Comeau is one that does.
However, export is removed from C++ in C++0x.

How do I export templated classes from a dll without explicit specification?

I have a dll that contains a templated class. Is there a way to export it without explicit specification?
Since the code for templates is usually in headers, you don't need to export the functions at all. That is, the library that is using the dll can instantiate the template.
This is the only way to give users the freedom to use any type with the template, but in a sense it's working against the way dlls are supposed to work.
Are you looking into exporting an instantiation of a template class through a dll? A class along the lines:
typedef std::vector<int> IntVec;
There is some discussion how to do this on:
http://support.microsoft.com/kb/168958
Another approach is to explicitly exporting each function you are interested in through a wrapper class working against this template instance. Then you won't clutter the dll with more symbols than you are actually interested in using.
When the compiler finds an instantiation of a template class, like MyTemplate<int>, then it generates the code for the template specialization.
For this reason, all the template code must be placed in an header file and included where you want to use it.
If you want to 'export' your template class, just place your code in an header file and include it where it's needed.
In your export control file.
#ifdef XXXX_BUILD
#define XXXX_EXPORT __declspec(dllexport)
#define XXXX_EXTERN
#else
#define XXXX_EXPORT __declspec(dllimport)
#define XXXX_EXTERN extern
#endif
where XXXX_BUILD is a symbol defined in your project.
To get your class exported.
XXXX_EXTERN template class XXXX_EXPORT YourClass<double>;
Where double is the type you want to instantiate the class with.
https://support.microsoft.com/en-us/help/168958/how-to-export-an-instantiation-of-a-standard-template-library-stl-clas