+ 2
Template instantiation with different project | Base derived class
Here code below: https://www.sololearn.com/en/compiler-playground/c4klNA8CnhM6 This code compiles fine and no issue. Issue arises when baseT class and derivedT class are part of different project. Due to this separation, setSlot method which is templated will not be defined by compiler as different project has this method usage. Now when derived class related project is build, it fails to find this method while linking with base class project dll. How to avoid this issue? https://sololearn.com/compiler-playground/c4klNA8CnhM6/?ref=app
14 Answers
+ 1
Seeing the more-explicit source code really helped.
I assume <class t> is a typo, and is actually <class T>.
Conventionally, common.h should be common.hpp. If it contains templates, it is incompatible with C.
-----
I see only two solutions for you. Neither is very elegant in my opinion, and it exposes some of my personal disdain for C++.
This is what I would do. Declare the add function as inline. In this way, add() is no longer a function symbol that causes conflict in the linker.
// common.h
template <class T> inline void add(T a, T b) { return a + b; }
Of course, inline makes a larger executable that could be a problem in some cases.
The other solution is to pre-declare in common.h each type of add() that you might use. It's very ugly!
// Definition for specific types
template <class T> void add(T a, T b) { return a + b; }
// Explicit instantiations
template void add<int>(int, int);
template void add<float>(float, float);
+ 3
It sounds like one of the projects is missing the template definition. Template definitions are typically placed in header files. Templates are processed by the compiler, not the linker. (The linker is what links references to dlls). Both projects should be including the template header file wherever the template is used.
+ 3
Yes, that situation would cause redefinition error. A common way to avoid redefinition is to use preprocessor directives in each header file that check for prior definition of a unique symbol defined in the header. It looks like this:
#ifndef HEADER_FILE_NAME
#define HEADER_FILE_NAME
// Entire header file content
#endif // HEADER_FILE_NAME
Some C++ compilers have a convenient #pragma option that handles this automatically if you place it at the beginning of every header file:
#pragma once
+ 2
Ketan Lalcheta it's puzzling to see that you got opposite results. What happens when you use the standard #ifndef/#endif approach?
+ 2
I misunderstood, expecting that common.h held a prototype declaration for add(), not the function definition itself. As you have found, it is problematic when you put code into header files (other than macros). Function code should be in a .cpp file so that it has its own global scope.
+ 1
Sounds good Brian
I have a query about redefiniton of function.
Suppose, I have a header file a.h in solution A which has function defined in header itself.
Now, another solution B has two files b.h and c.h and both of these includes a.h. . does this not mean solution B has two definition of header function (one via b.h and other via c.h ) causing redefinition error?
+ 1
Please, let us sharpen this point in question. Earlier you mentioned that common.h has the function defined as:
void add() {}
Instead, a function prototype for add() in common.h should look like:
void add();
And then in a .cpp file, there should be:
void add() {}
Is that how it really appears?
0
Hi Brian
I observed very different outcome.
I have four files like Header1.h , Header2.h , Common.h and Source.cpp
All three header files have #pragma once defined at the start of the header file
Header1.h and Header2.h includes Common.h
Source.cpp includes both Header1.h and Header2.h
Common.h has function defined as void add() {}
Compiling this solution works and builds successfully.
To my surprise, It still compiles successfully even though I remove the pragma statements. Why it works without pragma protection?
0
Scenario 2:
I have four files like Common.h , Source.cpp and Source2.cpp
Common.h file has #pragma once defined at the start of the header file and has one function defined as void add() {}
Common.h is included in Source.cpp and Source2.cpp
This set up fails to compile as Add function is defined in two units Source.obj and Source2.obj
0
Scenario 2 is I am damn sure that will not be protected by either IFNDEF or pragma
Scenario 1 is very weird and should happen without guards. It works with or without pragma and ifndef
0
Yeah. Correct. Function definition in .cxx files.
With this, I have my initial problem causing me build issue.
That is , template function declaration in header and definition in cpp file. This project is built first.
Now, other project includes header only and could not find definition causing build issue
0
Let me do it again as below:
Scenario 1 :
Project1:
common.h
template<class t> void add(T a,T b);
common.cpp:
template<class t> void add(T a,T b) {return a+b;}
Project1 is build independently no issue.
Project2:
main.cpp:
includes common.h
calls add(1,2)
This project 2 fails to compile as template definition is not in header file. If I move definition from common.cpp to common.h, it works.
However, moving definition to common.cpp fails in different scenario as discussed below:
Scenario 2 :
Project1:
common.h
template<class t> void add(T a,T b) {return a+b;}
Project1 is build independently no issue.
Project2:
test1.cpp:
includes common.h
calls add(1,2)
test2.cpp:
includes common.h
calls add(3,4)
This fails to compile project2 as it finds add function definition in both test1.obj and test2.obj (from common.h)
All these scenarios tried with #pragma once and #ifndef for common.h , but error remains as it is.
0
Thanks @Brian
0
You're welcome, Ketan Lalcheta