[]KAOS[]Casey wrote on Sep 9
th, 2016 at 12:45am:
forward declaring the TArray<TCHAR> caused a linker error
What do you mean by forward declaring the TArray<TCHAR>? The language rules forbid declarations like
class TArray<TCHAR>;
You can forward-declare the entire template
template <class T>
class TArray;
but not its specializations.
If you're referring to explicit instantiation of TArray<TCHAR>
template class TArray<TCHAR>;
then it could make sense only in DLL that is supposed to
export member functions of TArray<TCHAR> that can later might be imported by other module.
When you tell the compiler that some function shall be imported from a DLL, you obviously need to ensure that some DLL really exports such a function. Otherwise, where should the linker obtain that function from?
Since it is impossible to export the entire template, you can export only a finite set of functions that can be generated from the template. The presence of generic definition of a member function like TArray::Remove won't magically make all its possible specializations exported. You can instantiate TArray with billions of types - TArray<char>, TArray<short>, TArray<MyClass1>, TArray<MyClass2>, ..., TArray<MyClass100500>, and so on, and every such a specialization TArray<BlaBlaBla> will have its own distinct member function TArray<BlaBlaBla>::Remove. Hence we have a reasonable question: what set of functions should be exported? Obviously, the compiler needs some hint regarding what set of functions we need.
However, all these things with exporting/importing may be unnecessary (you should know better the specifics of the UE API, because you were working with it; I'm just speaking about the general theory - templates & DLLs). Then you could remove dllimport specifiers and rely on implicit instantiation of templates from headers.
Quote:The additions with ENGINE_API being removed,
or the forward declaration of TArray<TCHAR> add these linker errors.
1>TextureMergerMain.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall TLazyArray<unsigned char>::TLazyArray<unsigned char>(class TLazyArray<unsigned char> const &)" (__imp_??0?$TLazyArray@E@@QAE@ABV0@@Z)
1>TextureMergerMain.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall TLazyArray<unsigned char>::~TLazyArray<unsigned char>(void)" (__imp_??1?$TLazyArray@E@@QAE@XZ)
1>TextureMergerMain.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall TLazyArray<unsigned char>::TLazyArray<unsigned char>(int)" (__imp_??0?$TLazyArray@E@@QAE@H@Z)
These messages clearly indicate that dllimport specifier is present and applied. The linker could previously omit issuance of these errors after detection of other errors.
Quote:All I had to do was add a few "Typename" declarations.
What is a typename declaration?
Quote:I've currently reduced it down to
FMipmap *M = new FMipmap( 0, 0,0);
M->DataArray(0);
where accessing DataArray(0) causes the linker error.
1>TextureMergerMain.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: unsigned char & __thiscall TArray<unsigned char>::operator()(int)" (__imp_??R?$TArray@E@@QAEAAEH@Z)
1>..\..\System\TextureMerger.dll : fatal error LNK1120: 1 unresolved externals
The same history - the compiler sees that TArray<unsigned char>::
operator() is odr-used, but does not instantiate the function definition from what you have in your header because of dllimport specifier. The linker fails to find the given function in any DLL and issues an error message.