Formation of a symbol definition for an instance of a C ++ template in a library

I would like to provide a library that provides template code. But I would also like to keep the maximum possible ownership of this code (generated code), when I can guess the use of different ordinary types of my template. Here is an example of what I'm trying to do:

lib1.h

#include <iostream>

template<int N>
void print_me() {
    std::cout << "I am function number " << N << std::endl;
}

lib1.cpp

#include "lib1.h"

/* Force symbols to be defined here. */
template void print_me<0>();
template void print_me<1>();

I will compile my library using:

g ++ -shared -fPIC lib1.cpp -o lib1.so

And when I use my library:

main.cpp

#include <lib1.h>

int main() {
    print_me<0>();
    print_me<1>();
    print_me<2>();
}

Compiled with

g ++ main.cpp -l1

, print_me < 0 > () print_me < 1 > () lib1.so print_me < 2 > (), ( nm - ). , , ! 0 1 lib1.so, . (0, 1 2) , . , 0 1 main.cpp, , ( main.cpp).

(, lib1.h) main.cpp, - ?

+4
3

++ 11: . main.cpp :

extern template void print_me<0>();
extern template void print_me<1>();

, print_me main.cpp ( 0 1). void print_me<0>(); void print_me<1>(); .

+3

, :

lib1.h:

#include <iostream>
template <int T> void print_me(void);
template <> void print_me<0>(void);
template <> void print_me<1>(void);

lib1_internal.h(: ):

#include <iostream>

template<int N>
void print_me_internal() {
    std::cout << "I am function number " << N << std::endl;
}

lib1.cpp:

#include "lib1.h"
#include "lib1_internal.h"

template <> void print_me<0>() {
  print_me_internal<0>();
}
template <> void print_me<1>() {
  print_me_internal<1>();
}

main.cpp :

$ g++ main.cpp -L. -l1
/tmp/ccZSDqkp.o: In function `main':
main.cpp:(.text+0xf): undefined reference to `void print_me<2>()'
collect2: ld returned 1 exit status

template <int T> void print_me(void) lib1.h , .

+3

.

//lib1.h    
template<int N>
void print_me();

//lib1.cpp
#include <iostream>
#include "lib1.h"
template <int printme>
void print_me()
{
  std::cout << printme << std::endl;
}

template void print_me<0>();
template void print_me<1>();

, : , ( print_me ), ( , , ). , , . , .cpp -, print_me < 2 > (). (imho) (++ 11):

//lib1.h
#include <type_traits>
template<int N>
typename std::enable_if<N == 1 || N == 0>::type print_me();

//lib1.cpp
#include <iostream>
#include "lib1.h"

template<int N>
typename std::enable_if<N == 1 || N == 0>::type print_me()
{
  std::cout << N << std::endl;
}

template void print_me<0>();
template void print_me<1>();

now the error "does not match the function for calling print_me ()", which is slightly better ... you could make a nested function with static_assert to make it even better.

+1
source

Source: https://habr.com/ru/post/1524709/


All Articles