C++ templated member function linker errors in client application - c++

I tried the recommendation here. I have the following class with a templated member function defined in the implementation as follows:
Header (with compiler DLL import directive evaluated as __declspec(dllimport) in client application):
class __declspec(dllimport) A {
...
template<typename T> bool func(T&) const;
}
Implementation:
template<typename T> bool A::func(T&) {...}
Due to some constraints, I can't define it the header. In the standalone library I get no build errors. But in the client application, built on the same platform using same compiler (x64 vs100), the linker error I get is:
error LNK2019: unresolved external symbol bool "public: bool __cdecl A::func(...)"
Appreciate any ideas on this. Thanks!

Your template code will not be generated until you actually instantiate it using some data type. For every data type different code is generated by the compiler.
Therefore if you want to use templated code that other code parts shall be able to use with any data type then the template implementations needs to be provided inline (i.e. in a header file of some sort). Only this way the template can be instantiated for any unknown data types in other compilation units.
If you only need a small number of variants of the template, say for int and float then you can declare explicit template instantiations. These declarations cause the compiler to actually output the template code for the given data types whether they're needed or not in a compilation unit. Then you also need to add dllimport/dllexport statements (in case of Windows Visual Studio compilers) for ex-/importing that code in/from a DLL.
More about this can surely be found in other discussions and documentation.

Make sure that your implemetation is in the same header (or it is taken in with some other #include statement) as the definition of the class. In this case it should work.

Related

Preventing template instantiations in a static library

I'm attempting to build a static library, containing definitions of DDS topics obtained from various IDL files. I'm using OpenDDS as my middleware.
When I create an IDL file containing a sequence<long>, compile it into my static library, and then link the static library against my application, I get linker errors involving multiple definition of symbols:
Error LNK2005 "public: void __cdecl TAO::unbounded_value_sequence<int>::length(unsigned int)" (?length#?$unbounded_value_sequence#H#TAO##QEAAXI#Z) already defined in TAO.lib(TAO.dll)
I believe this is because my static library contains a template instantiation of unbounded_value_sequence, and my application also contains an instantiation. It seems to be coming from within ACE TAO, which is used by OpenDDS.
I'm looking for a way to avoid instantiating the template in my static library altogether, so that it can just use the definition within the application when they are linked together. I tried adding the following:
extern template class TAO::unbounded_value_sequence<int>;
This produced the following error:
Error C2961 'TAO::unbounded_value_sequence<CORBA::Long>': inconsistent explicit instantiations, a previous explicit instantiation did not specify '__declspec(dllimport)'
I've tried to locate that instantiation, but its not in my code. It may be within ACE itself.
The problem does not occur if I build everything in the one project, but that is not an ideal solution.
What you have to do to use extern templates is a bit different. Indeed, declaring the extern template will prevent it's instanciation. But you will need an instanciation somewhere. That somewhere is usually in a cpp with the name of the template you want to compile.
unbounded_value_sequence.h:
// template struct here
extern template class TAO::unbounded_value_sequence<int>;
extern template class TAO::unbounded_value_sequence<long>;
// and every other instantiation you want to be in your static library
unbounded_value_sequence.cpp:
#include "unbounded_value_sequence.h"
// Here you compile them one time.
template class TAO::unbounded_value_sequence<int>;
template class TAO::unbounded_value_sequence<long>;
// and every other instantiation you want to be in your static library
That will make your template to be instantiated one time only, inside your library. The compiler will generate a unbounded_value_sequence object file that contains your template instantiations. They will exist only there.
Don't forget that you still need to make your template implementation visible in the header if you want users of your library use your template class with theirs.

Should visibility/export macros be applied to templates when writing a library?

When building a C++ DLL or shared library __attribute__((__visibility__("default"))) or __declspec(dllexport) is frequently attached via a macro to those concrete symbols (classes, functions, etc) that should be made available to consumers of the library, with the other symbols defaulted to have internal visibility.
But what should be done about inline functions or templates?
It seems that for inline functions the answer should be that no annotation is needed. If the consumer of the header defining the inline function actually inlines the function, then there is no symbol needed. If the consumer emits an out-of-line definition instead, that is still OK. The only wrinkle is that the definitions of the inline function inside the DLL and inside each consuming library may differ. So, you could get some trouble if you were expecting to reliably compare the addresses of inline functions, but that seems pretty sketchy anyway.
Given that argument, it would seem that since templates bodies are typically entirely visible to the consuming TU, that the same logic would apply.
I feel like there are probably some subtleties here with respect to 'extern template' and explicit instantiations.
Does anyone have concrete guidance on how visibility attributes should adhere to inline functions and templates?
Inline functions are not externally visible (have no linkage, IIRC), so they are not exportable from a DLL. If they are to be public, then they are fully written in the header file of your library and every user recompiles it.
And as you say in the question, since the inlined code is recompiled in every module that uses the library, so for future versions of the library there may be problems.
My advice for inline functions in a shared library is that they should be used only for really trivial tasks or for absolutely generic functions. Note that converting a public inline function to a non-inline function is an ABI breaking change.
For example:
A memcpy-like funcion. Inline!
A bswap-like function. Inline!
A class constructor. Do not inline! Even if it does nothing now, You may want to do something in a future version of the library. Write a non-inline empty constructor in the library and export it.
A class destructor. Do not inline! Same as above.
The fact that an inline function can have several different addresses, in practice, has little importance.
About extern template and explicit instantiations, with a bit of care, they can be used to export a template from a library. If the template instantiations are limited to a specific set of cases, you can even avoid to copy the template code to the header files.
NOTE 1: In the following examples I will use a simple function template, but a class template will work exactly the same.
NOTE 2: I'm using the GCC syntax. The MSC code is similar, I think you already know the differences (and I don't have a MSC compiler around to test).
Example 1
public_foo.h
template<int N> int foo(int x); //no-instantiable template
shared_foo.cpp
#include "public_foo.h"
//Instantiate and export
template __attribute__ ((visibility("default")))
int foo<1>(int x);
template __attribute__ ((visibility("default")))
int foo<2>(int x);
program.cpp
#include "public_foo.h"
int main()
{
foo<1>(42); //ok!
foo<2>(42); //ok!
foo<3>(42); //Linker error! this is not exported and not instantiable
}
If instead, your template should be freely instantiable, but you expect it to be frequently used in a particular way, you can export these ones from the library. Think of std::basic_string: it is most likely to be used as std::basic_string<char> and std::basic_string<wchar_t>, but unlikely as std::basic_string<float>.
Example 2
public_foo.h
template<int N> int foo(int x)
{
return N*x;
}
//Do not instantiate these ones: they are exported from the library
extern template int foo<1>(int x);
extern template int foo<2>(int x);
shared_foo.cpp
#include "public_foo.h"
//Instantiate and export
template __attribute__ ((visibility("default")))
int foo<1>(int x);
template __attribute__ ((visibility("default")))
int foo<2>(int x);
program.cpp
#include "public_foo.h"
int main()
{
foo<1>(42); //ok, from library
foo<2>(42); //ok, from library
foo<3>(42); //ok, just instantiated
}
I think what you are asking boils down to these 2 questions:
When do I need to explicitly export a symbol with __attribute__((__visibility__("default")))?
The rule here is that if the implementation for the method is internal to your shared library (usually, it's in the .cpp file with a declaration in the external .h) you need to mark the declaration for that symbol as externally visible when compiling your shared library. If you fail to do so, compiling anything that uses that method in an external library will complain at link time - so this problem is easy enough to catch with testing.
This is assuming you've also added -fvisibility=hidden to internalize all symbols by default.
Is it harmful to add __attribute__((__visibility__("default"))) to inline functions or template functions with a definition that is externally visible?
It's not, since a common use case for default visibility is to mark entire classes for export - which may comprise both outline and inline methods. In this situation, inline methods will be inline (in any translation unit that uses it) and generate no external symbol. If you later choose to outline the method, the symbol visibility will take effect.
For templates, explicit template instantiation is just a mechanism to allow you to create an outline definition for the template method - and the same rules apply as for ordinary inline/outline methods.

C++ templating, passing a function pointer with a parameterized return type

I want to parameterize the return value of a function to match the return value of a function pointer I pass it. I've only dealt with java generics before, so there's a good chance I'm completely missing something here.
the function looks like:
<in header>
template <typename T> static T getItems(const char* xpath, T (*getThings)(xpath_node_set*));
<in body>
template <typename T>
T XMLAdapter::getItems(const char* cpath, T(*getThings)(xpath_node_set*)){
return getThings(head.select_nodes(path));
}
and the function i'm passing into it looks like this:
size_t handler(xpath_node_set* in){
return in->size();
}
And the error i'm getting is:
Error 1 error LNK2019: unresolved external symbol \
"public: static unsigned int __cdecl XMLAdapter::getItems<unsigned int>(char const *,unsigned int (__cdecl*)(class pugi::xpath_node_set *))" (??$getItems#I#XMLAdapter##SAIPBDP6AIPAVxpath_node_set#pugi###Z#Z) \
referenced in function _wmain C:\Users\Adam\SkyDrive\Documents\proj\ray\ray\ray.obj ray
What gives?
remove the static from the prototype, it makes your function file local (i.e. invisible to other TUs).
Generally the function template definition should appear in the header, not a separate .cpp file.
Template functions need to be fully implemented (not just declared) in the header or you'll hit linker errors like this, if your caller and the template function are not in the same .cpp file.
Think about it this way:
When you run the compiler on your code, you're actually compiling a separate .obj file for every single .cpp file. From the point of view of the compiler, these are completely independent black boxes. Every .cpp file could be compiled in parallel, and there are zero dependencies between them. The only dependcies are function declarations (specified in headers) which say "yeah, yeah...someone else is implementing this, let the linker complain if it can't find it."
When you have a template function, what you're really making is a recipe for how to make a function. If you have Foo<T> and you want to call it with int's and with string's, there are literally two generated functions that are completely symbolically different in your final binary: Foo<int> and Foo<string>.
That said, if you have your implementation of your template function in a separate .cpp file from someone who is trying to call a specialized version of it, they have no way to "cook" a new version of that function with whatever template arguments they are supplying. All they have is a header that says "Foo<T> is a function someone else implemented" to appease the linker. But your TemplateImplementation.cpp has no way of knowing that it should have generated a Foo<int> and a Foo<string>.
This is why you'll always see template libraries shipped as header-only libraries. No one could ship you a lib with compiled template functions if they wanted to, because they can't generate the functions until you have called specific versions.

C++ linking for an overloaded << function (logger class)

I'm currently writing a logger for my C++ project (I need it to have near to no dependences, so I don't want to take a prewritten one). It contains this function:
template <typename T>
Logger& Logger::operator<<(T f) {
m_file<<f;
return *this;
}
The logger.cpp code compiles, but when I call the log functions in my main.cpp, I have this compiler error:
/home/tuxer/prog/cpp/PRay/server/src/main.cpp:110: undefined reference to `Logger& Logger::operator<< <int>(int)'
for this line of code :
log<<lul; (lul being a int variable equals to 2)
The logger.o file is correctly included, as the Logger::init() function works properly and doesn't raise any linking error.
Thanks :)
Since you have non-inline templates, you need to force instantiation. See for example How do I force a particular instance of a C++ template to instantiate?.
The simple thing to do is to put the Logger::operator<< template in the header file. The compiler will automatically instantiate the versions it needs, and the linker will remove the duplicates (well, at least the ones that weren't inlined).
You shouldn't need to force instantiation unless your linker is old (e.g. gcc 2.7 or earlier).
This is the general rule with template code: put the definitions in the header file unless you have a good reason not to.
See Why can templates only be implemented in the header file? as well.

template class, implementation code causing linking issues

I currently have a program where my main code is in a file main.cpp.
Main.cpp includes a header file "class.h" that declares a class that is used within main.cpp.
Also in main.cpp I have function declarations that declare the functions I use within main.cpp.
The code for these functions is in a separate .cpp file fucntions.cpp.
Like main.cpp, functions.cpp also includes class.h as the class type is used within the functions.
class.h contains the class declaration only.
The implementation code for class.h is in a separate .cpp file classimplementation.cpp.
It all works fine until I try to make the class in class.h a template class.
Then I get linking problems. Research and testing has shown me that this is because the definition of the template class functions needs to reside in class.h with the declaration.
I therefore took the required code out of classimplementations.cpp and put it into class.h.
This did solve my original linking issues but instead I get more linking errors that seem to be telling me I am trying to redefine the functions that I moved to into class.h.
This I think is because class.h is being called by main.cpp and again by functions.cpp.
Therefore the functions in class.h are being defined twice:
Error 41 error LNK2005: "public: __thiscall RecordPocket::RecordPocket(int)" (??0?$RecordPocket#VT####QAE#H#Z) already defined in classimplementation.obj functions.obj
I know that class implementation code should really be kept out of include files but due to the template class limitation of having to keep the class functions local I appear (in my novice mind) to have no choice.
Has anyone been in this scenario and can offer any advice.
I have tried surrounding the functions I moved from classimplementation.cpp to class.h with the standard ifndef CLASSIMP, #define CLASSIMP code and PRAGMA ONCE but neither make any difference.
If all else fails I will move the functions from functions.cpp into main.cpp so that class.h gets called just the once but I’d rather find out what I’m doing wrong as I’m sure it will happen again.
You could keep the template functions inside the template<> class what{/HERE/};
template<typename T>
class MyTempClass{
void myFunctions{
// code here
}
}
EDITED: I removed the code corrected by Glen
I think your problem is revolves around these issues. As you have implied any template function definition (i.e. template function of member function of a template class) needs to be fully expressed in the .h file because when the compiler finds a specific instance of the template it needs to build the function.
You figured this out and moved some implementation into your class.h file. Now if the linker find a MyFunction() in more than one module then is just discards one of them a no linker error is reported.
However you can't define the same non-template function in two different modules as this generates the error you are getting above. So I suspect you also moved some non-template functionality into the .h file; thus including it in two separate obj files and generating the linker error. This theory is support by your quoted error message as I note __thiscall RecordPocket::RecordPocket(int) does not appear to be template.