Can someone solve the mystery of why do I get linking errors if I take the address of a variable that should go in a template parameter only if I make the variable const
, constexpr
or static
, but not oherwise?
The piece(s) of code below are part of a larger project, but I extracted the exact same structure:
CMakeLists.txt
project(fun)
add_library(fun SHARED fun.cpp)
add_executable(main main.cpp)
target_link_libraries(main fun)
fun.cpp
#include "fun.h"
BlaaUser testBlaa(int)
{
return BlaaUser();
}
fun.h
#pragma once
#include "types.h"
extern BlaaUser testBlaa(int);
main.cpp
#include "fun.h"
int main()
{
auto b = testBlaa(2);
}
types.h
#pragma once
struct P
{
char n;
};
template<const P* S>
struct Blaa
{
Blaa() {}
char blaa{S->n};
};
//constexpr
//static
//const
P p{}; // <-- Here, right now it works. If I uncomment any of the specifiers, I get errors, see below
using BlaaUser = Blaa<&p>;
If I add any kind of specifier I get the following errors:
Scanning dependencies of target fun
[ 25%] Building CXX object CMakeFiles/fun.dir/fun.cpp.o
[ 50%] Linking CXX shared library libfun.so
[ 50%] Built target fun
Scanning dependencies of target main
[ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.o
In file included from /home/fld/work/tmpl_test/main.cpp:1:
/home/fld/work/tmpl_test/fun.h:5:17: warning: ‘BlaaUser testBlaa(int)’ used but never defined
5 | extern BlaaUser testBlaa(int);
| ^~~~~~~~
[100%] Linking CXX executable main
/usr/bin/ld: CMakeFiles/main.dir/main.cpp.o: in function `main':
main.cpp:(.text 0x12): undefined reference to `testBlaa(int)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/main.dir/build.make:104: main] Error 1
make[1]: *** [CMakeFiles/Makefile2:97: CMakeFiles/main.dir/all] Error 2
make: *** [Makefile:103: all] Error 2
I sort of have the feeling that it has to do with the address of an object (as per the standard: For pointers to objects, the template arguments have to designate the address of a complete object with static storage duration and a linkage (either internal or external) ) but I'm just a bit confused because if everything goes in one file all is ok, the problem comes when it's split up in libraries ...
Does anyone have any explanations?
CodePudding user response:
The additional specifiers (e.g const
, constexpr
) makes the template parameter have internal linkage, which subsequently makes testBlaa(int)
have internal linkage. It works if you do
extern const P p{}
right? Maybe Why does the following method get internal linkage? is similar?