Home > Mobile >  Address of a constexpr in a template parameter
Address of a constexpr in a template parameter

Time:04-29

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?

  • Related