问题
Background:
I currently have a game engine project structured in visual studio so that my 'Engine' is compiled into a dll for another project 'Game' to consume. The idea being I can swap out different game projects and still use the same engine dll code. Within my engine code I'm creating my own framework for which all other engine code will use. This will help to separate my implementation from the rest of my code and make modification easier if need be.
Since all my framework code with be used within the dll itself and not within 'Game' I thought I could implement templates. However, I still receive the 'undefined symbol' error anytime I try and implement templates with the Engine framework.
Issue:
Is there a way to get around the 'undefined symbol' errors for templates from the linker within my dll without having to explicitly define every type my template will consume (ex. class template MyClass<int>
, class template MyClass<float>
, etc.)? If not, are there any suggestions on different ways I could implement my engine and different game projects to still keep things flexible? Thanks for any input.
P.S. I don't want to have to explicitly define all types a templated class could use since that would get rather large if I wanted to create say my own vector template class (as I would have to define A LOT of different classes).
回答1:
Template intantiations are generated at compile time, so if you don't want to individually declare all possible instantiations then you must move all template definitions to be included with the header file.
One common way of doing this is for each class to have all of the template definitions in an inline file e.g a .inl
or .cxx
file, and then to include that inline file at the end of the corresponding header file.
For example, for a class Foo
with a single templated function:
Contents of Foo.hpp
:
class Foo
{
template <typename T>
void bar();
};
#include "Foo.inl" // Include template definitions
Contents of Foo.inl
:
template <typename T>
void Foo::bar()
{
// body
}
That way, whenever Foo::bar<T>
is used with a new T
then an a new template instantiation will be generated.
回答2:
Templates are supposed to be inline code. Their code created at code generation step when compiler encounters use of template, with code for that use case. In general attempt to force compiler to create class based on template is a fallacy , performance issue and inconvenience that opposes the purpose of having templates.
In general you need to declare object (variable) of specialized template to force compiler to generate one, if you have limited count of specialized variants< you need to declare them all. Even in that case compilers try avoid of creating new functions, unless they are virtual.
Most template libraries out there fully declare code of methods in headers, and may have no binary object files at all. Just do like mock_blatt said in comment, make declarations of templates in header and implementations of methods and friends in include file used from header.
回答3:
"I don't want to have to explicitly define all types a templated class could use since that would get rather large"
What exactly do you expect the DLL to contain? Either it contains MyClass<float>
or it doesn't. And the compiler would instantiate MyClass<T>
for every type it knows, your DLL would be huge.
来源:https://stackoverflow.com/questions/40798397/getting-around-issues-with-templates-inside-dll-in-c