0

I've been able to pinpoint the problem. enter image description here

The contents of the files A,B,Main (as shown in the image) are as follows:

cmake_minimum_required(VERSION 3.13)

add_library(class_a ${CMAKE_SOURCE_DIR}/modules/class_a/class_a.cpp)
target_include_directories(class_a PUBLIC ${CMAKE_SOURCE_DIR}/modules/class_b)
target_link_libraries(class_a PUBLIC class_b)

cmake_minimum_required(VERSION 3.13)
add_library(class_b ${CMAKE_SOURCE_DIR}/modules/class_b/class_b.cpp)

and

cmake_minimum_required(VERSION 3.13)

add_executable(test_class_a test_class_a.cpp)
target_include_directories(test_class_a PUBLIC ${CMAKE_SOURCE_DIR}/modules/class_a/)
target_link_libraries(test_class_a PUBLIC class_a)

The classes have their own *.hpp and *.cpp files (the first two are the *.cpp-files with definitions, and the last is the test_class_a.cpp:

#include "class_a.hpp"
#include "class_b.hpp"

template<typename t>
class_a<t>::class_a() : field(42) {}
template<typename t>
class_a<t>::~class_a() { field^= field; }

template<typename t>
void class_a<t>::do_it() {
    class_b<t> b;
    b.do_something();
}

#include "class_b.hpp"
template<typename t>
class_b<t>::class_b() { info= {}; };
template<typename t>
void class_b<t>::do_something() { return ; }

#include <memory>
#include "class_a.hpp"

int main() {
    auto ptr= std::make_unique<class_a<int>>();
    ptr->do_it();
    return 0;
}

I read elsewhere that this is always the problem with templates and unique_ptr, and one of the solutions is to put everything into a single file, without separating the header and definitions. I wonder if this is the only way, or is there some CMake-way of keeping the same structure and modularity, and still being able to compile? The above code gives the compile error:

[ 33%] Built target class_b
Scanning dependencies of target class_a
[ 50%] Building CXX object modules/class_a/CMakeFiles/class_a.dir/class_a.cpp.o
[ 66%] Linking CXX static library libclass_a.a
[ 66%] Built target class_a
Scanning dependencies of target test_class_a
[ 83%] Building CXX object modules/tests/CMakeFiles/test_class_a.dir/test_class_a.cpp.o
[100%] Linking CXX executable test_class_a
/usr/bin/ld: CMakeFiles/test_class_a.dir/test_class_a.cpp.o: in function `main':
/home/ilo/CLionProjects/mwe/modules/tests/test_class_a.cpp:6: undefined reference to `class_a<int>::do_it()'
/usr/bin/ld: CMakeFiles/test_class_a.dir/test_class_a.cpp.o: in function `std::_MakeUniq<class_a<int> >::__single_object std::make_unique<class_a<int>>()':
/usr/include/c++/8/bits/unique_ptr.h:831: undefined reference to `class_a<int>::class_a()'
collect2: error: ld returned 1 exit status
make[3]: *** [modules/tests/CMakeFiles/test_class_a.dir/build.make:86: modules/tests/test_class_a] Error 1
make[2]: *** [CMakeFiles/Makefile2:129: modules/tests/CMakeFiles/test_class_a.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:141: modules/tests/CMakeFiles/test_class_a.dir/rule] Error 2
make: *** [Makefile:131: test_class_a] Error 2
Ilonpilaaja
  • 1,169
  • 2
  • 15
  • 26
  • 1
    1) Why `target_include_directories` for `class_a` points to `/modules/class_b`? 2) When you post error log, it will be much better if you post log for `make VERBOSE=1` not `make`. 3) Templates should be implemented in headers, but that's not a problem of CMake. – Evg Nov 16 '19 at 16:26
  • 1
    CMake and `unique_ptr` have nothing to do with the problem. You are not following the C++ language rules for templates. Note that the linked duplicate explains a workaround if you really need to separate class definition and method implementations in separate files: explicit instantiation. – walnut Nov 16 '19 at 16:28
  • 1
    I meant "separate translation units". Separate files are not a problem anyway as long as you include the file with the method implementations in the header with the class definition. (But then you shouldn't compile the implementation file as separate translation unit and so the `.cpp` naming is probably inappropiate.) – walnut Nov 16 '19 at 16:35
  • explicit instantiation solved the problem, plus I've learned something solid with CMake. Thank you. – Ilonpilaaja Nov 16 '19 at 16:46

0 Answers0