1

I have just tried to test how the compiler behaves with template in multi files. In each .cpp file, I defined a class template with the same name but a bit different implementation. See the files below:

  • test.h
#include <iostream>

//#define FROM_MAIN_CPP     //for choosing main() from which .cpp file
  • NOT_main.cpp
#include "test.h"

//template definition
template <typename T> class cls {
public:
    T prop;
    cls(T _val) : prop(_val) {
        std::cout << "from NOT_main.cpp\n";
    }
};

//template instantiation
template class cls<int>;    
extern template class cls<float>;   //expect definition in main

//testing...
#ifndef FROM_MAIN_CPP
int main(void) {
    cls<int> int_obj(19);
    cls<float> float_obj(1.9f);     //expect definition in main
}
#endif
  • main.cpp
#include "test.h"

//template definition
template <typename T> class cls {
public:
    T prop;
    cls(T _val) : prop(_val) {
        std::cout << "from main.cpp\n";
    }
};

//template instantiation
extern template class cls<int>;     //expect definition in NOT_main
template class cls<float>;

//testing...
#ifdef FROM_MAIN_CPP
int main(void) {
    cls<int> int_obj(19);     //expect definition in NOT_main
    cls<float> float_obj(1.9f);
}
#endif

Now I try to compile with the main() functions in each .cpp file. See my test here: https://drive.google.com/drive/folders/1AmSZCSVZhJwNP8AxJ0saYeLZANWeX6v2?usp=sharing

I know the extern keyword helps the compiler prevent multi instantiations in translation units. I expected when I explicitly instantiated the template defined in first file, then used the declaration with extern in other ones, so the template definition used should be the definition in the first.

In detail, with the main() in NOT_main.cpp, it behaved as I expected. But with the main() in main.cpp, why did the compiler choose template defined in main.cpp despite using extern.

It would be appreciated if you could point out what's wrong in my understanding. Thanks and regards.

wohlstad
  • 12,661
  • 10
  • 26
  • 39
Cong Hau
  • 29
  • 3
  • Perhaps this helps: [Why can templates only be implemented in the header file?](https://stackoverflow.com/q/495021/1553090) – paddy May 09 '23 at 02:17
  • 2
    This is ODR violation. Program is simply malformed and there are no guarantees. – ALX23z May 09 '23 at 02:19
  • 2
    The different implementations are required to be identical. Otherwise, the program is ill-formed, no diagnostic required. – Eljay May 09 '23 at 02:23
  • @Eljay "different implementation are required to be identical" that's an oxymoron. – ALX23z May 09 '23 at 02:32
  • @Eljay I know but just for test. I even tested and found that the compiler randomly choosed one of the class template definitions if they were defined through multi files because the templates are the weak symbols. But I wonder if we define a template in `first.cpp` file and explicitly instanciate one instanciation right in that file, then in `another.cpp` we also define the template but just declare the instanciation with `extern`, so the template defintion used should be from `first.cpp` where we have explicitly instanciated. Is it right? – Cong Hau May 09 '23 at 03:40
  • ODR violation is IFNDR. – Jason May 09 '23 at 04:10
  • 1
    "I know I cannot expect anything specific but I expect something specific". Just don't. – n. m. could be an AI May 09 '23 at 04:47

0 Answers0