I have a Project in CMake including a shared library.
To use templated Functions i have to explicitly instantiate or specialize them because the compiler can't know for which types they will be needed from outside the library.
CMake provides a Makro that produces the needed __declspec(dllexport) / __declspec(dllimport)
I have prefixed the declaration of my function with that macro and everything works as intended.
Now when I add a Specialization for that function it strangely also needs that macro,
otherwise the linker creates an error (Ex.: undefined reference to `_imp__Z3addIdET_S0_S0')
There is no immediate Problem here, I am just confused as to why the Specialization needs the declspec again.
Even more so since simple instantiations don't seem to need it.
I am using gcc 10.2.0 from msys2 and ninja 1.10.2 on Windows 10
Edit:
I looked at the other question before asking and it does not answer mine.
When compiling other.cpp the compiler has acces to everything about the template function.
So when compiling main.cpp add<int> is already present in libother.dll and add<double> should be as well.
I guess add<double> is only exported into the .dll with __declspec(dllexport)
The question is: why is add<int> exported without it then?
Example:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.19.4)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) #Put Lib and Exe into the same Folder
project(Test)
add_library(Other SHARED other.cpp)
target_include_directories(Other PUBLIC .)
include(GenerateExportHeader)
generate_export_header(Other
EXPORT_MACRO_NAME OTHER_EXPORT
EXPORT_FILE_NAME OtherExports.h)
target_include_directories(Other PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
add_executable(Test main.cpp)
target_link_libraries(Test Other)
main.cpp:
#include <iostream>
#include "other.h"
int main(){
std::cout<<add(1,2)<<std::endl;
std::cout<<add(1.0, 2.0)<<std::endl;
return 0;
}
other.h:
#include "OtherExports.h"
template<typename T>
OTHER_EXPORT T add(T a, T b);
other.cpp:
#include "other.h"
template<typename T>
T add(T a, T b){
return a+b;
}
//instantiation for int without declspec macro, compiles!
template int add<int>(int, int);
//specialization for double without declspec macro, doesn't compile!
template <> double add<double>(double a, double b){
return a-b;
}
//Specialization for double with declspec macro, compiles!
/*template <> OTHER_EXPORT double add<double>(double a, double b){
return a-b;
}*/