The following code reproduces an error that I get in VS2005: I have a template function like
template <typename T> bool foo(T x, T y) {
struct bar {
public:
T t;
bool CompLT(const bar& that) {
return (this->t) < (that.t);
}
};
bar X, Y;
X.t = x;
Y.t = y;
return X.CompLT(Y);
}
in a header file A.h. When I now use the header in two compilation units B.cpp and C.cpp VS2005 complains with the error
error LNK2005: "public: bool __thiscall `bool __cdecl foo<float>(float,float)'::`2'::bar::CompLT(struct `bool __cdecl foo<float>(float,float)'::`2'::bar const &)" (?CompLT#bar#?1???$foo#M##YA_NMM#Z#QAE_NABU1?1???$foo#M##YA_NMM#Z##Z) is already defined in B.obj .
How can I fix this error? Is this a problem with VS2005 or do I have to move the definition of the struct out of the local function scope and make it a template?
Have you used include guards ?
Try adding the following and remove any object file (ending with .o)
#ifndef A_H
#define A_H
//your header
#endif
From the comments being made it is clear that this is a bug in VS2005. As no one could provide some insight into the exact source of the problem I will give my solution: I moved the function into a static template class and defined the inner struct as a private local within that class template.
Related
I have a struct containing two functions, one of which is a template function that calls the other. For the sake of organization, I'd like to separate these member functions into separate implementation files instead of defining them all in main.cpp. Visual Studio throws an unresolved external symbol error.
header.hpp:
#pragma once
struct Structure {
void function();
template<bool> void templateFunc();
Structure();
};
implementation.cpp:
#include "header.hpp"
void Structure::function() { return; }
main.cpp:
#include "header.hpp"
template<bool N> void Structure::templateFunc() { return function(); }
Structure::Structure() {}
int main() {
Structure object;
object.function(); // no error
object.templateFunc<0>(); // unresolved external symbol
}
LNK2019: unresolved external symbol 'public: void __cdecl Structure::function(void)' referenced in function 'public: void __cdecl Structure::templateFunc<0>(void)'
When I define the function in main, it compiles and runs.
main.cpp:
#include "header.hpp"
void Structure::function() { return; } // defined in main
template<bool N> void Structure::templateFunc() { return function(); }
Structure::Structure() {}
int main() {
Structure object;
object.function(); // no error
object.templateFunc<0>(); // no error
}
I was initially under the suspicion that my compiler was excluding implementation.cpp, but it fails to compile when syntax errors are present. Oddly, I don't receive a multiple declaration error when the function is defined in both files. I tried reprogramming this from scratch on another device and encountered the same error. I've ensured everything is explicitly included in compilation.
The code I'm hoping for is functionally identical to the code I've found works, but this example represents a larger project I'd like to organize.
Why is this happening? How can I define this function in a separate file?
When I have a class that can be boiled down to something like this:
// test.hpp
class Test{
public:
template<typename T> static T value;
};
template<typename T> Test::value = {};
I can use this class when I only look up an instantiated value in one .cpp file. But when I try to use this in multiple .cpp files I get an already defined linker error.
//somefile1.cpp
include "test.hpp"
void fn(){
int i = Test::value<int>;
}
// somefile2.cpp
include "test.hpp"
void otherfn(){
// public static int value already defined in somefile1.obj
int j = Test::value<int>;
}
Putting template<typename T> Test::value = {} into its own .cpp file gives an unresolved external error for all uses. What's the problem?
The following code (this is a simplified version of what I need) does not link
In *.h file:
class InterfaceFunctionField2 {
public:
template<class outputType> outputType to() { return outputType(); }
};
In *.cpp file
template<> double InterfaceFunctionField2::to<double>()
{ return 3.; }
This class sits in a static library.
I am getting "error LNK2005: "public: double __thiscall InterfaceFunctionField2::to(void)const " (??$to#N#InterfaceFunctionField2##QBENXZ) already defined in ..." and a "second definition ignored" warning LNK4006
I define InterfaceFunctionField2::to() specialization only once and I do not #include *.cpp files....
I have looked up on internet (e.g. here) and this type of code seems to be ok but the linker disagrees. Could you help? Thanks.
You need to also declare the specialization in the header.
//header.h
class InterfaceFunctionField2 {
public:
template<class outputType> outputType to() { return outputType(); }
};
template<> double InterfaceFunctionField2::to<double>();
//implementation.cc
template<> double InterfaceFunctionField2::to<double>()
{ return 3.; }
The code in your link works because the specialization is visible to that translation unit.
All code From what I've read, A1 & A2 are identical, but I don't if A3 is identical to A2. I know the code will compile since all of the A classes are tmemplated.
Note: All of the class & method declarations are in a .h file.
template <typename _Ty>
class A1 {
public:
A1();
void foo() { ... }
};
template <typename _Ty>
class A2 {
public:
A2();
void foo();
};
template <typename _Ty>
inline void A2<_Ty>::foo() { ... }
template <typename _Ty>
class A3 {
public:
A3();
void foo();
};
template <typename _Ty>
void A3<_Ty>::foo() { ... } // note: No inline keyword here.
P.S. I've seen variants of this question on stackoverflow, but not this exact question.
Yes, it's meaningful, but doesn't have much effect when combined with templates.
The major effect of the inline keyword is to tell the compiler that this function may appear with the same definition in multiple compilation units, so it needs to be flagged as "select-one" for the linker (so you don't get multiple definition errors). Templates already have this feature.
inline also is a hint to the compiler that you think the function should be inlined, but the compiler usually makes the final decision on inlining optimizations on its own.
Is inline keyword meaningful if function is defined in header file?
It is. Following project will produce linker error on both msvc and g++ BECAUSE of the omission of inline keyword:
main.cpp:
#include "a.h"
int main(int argc, char** argv){
A obj;
obj.f();
a();
b();
return 0;
}
a.h:
#ifndef A_HEADER
#define A_HEADER
class A{
public:
void f();
};
void a(){
}
void b();
void A::f(){
}
#endif
b.cpp:
#include "a.h"
void b(){
A obj;
obj.f();
a();
}
*.pro file (for Qt 4 build system):
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
HEADERS += a.h
SOURCES += b.cpp main.cpp
Compilation output:
cl.exe:
main.obj : error LNK2005: "void __cdecl a(void)" (?a##YAXXZ) already defined in b.obj
main.obj : error LNK2005: "public: void __thiscall A::f(void)" (?f#A##QAEXXZ) already defined in b.obj
debug\1234.exe : fatal error LNK1169: one or more multiply defined symbols found
g++:
debug/main.o: In function `Z1av':
D:\c++\1234/a.h:6: multiple definition of `a()'
debug/b.o:D:\c++\1234/a.h:6: first defined here
debug/main.o:D:\c++\1234/a.h:11: multiple definition of `A::f()'
debug/b.o:D:\c++\1234/a.h:11: first defined here
collect2: ld returned 1 exit status
make[1]: *** [debug/1234.exe] Error 1
make: *** [debug] Error 2
Now, why do you think this happens? Because compiler inserts contents of header file into *.cpp file when compiling. Since function isn't "inline", its name is made known to the linker, and each .obj/.o file will get its own unique copy of A::f() and a(). Linker won't know which you're supposed to use and will complain. If you make functions inline, everything will work fine.
However, templates are another story.
I am trying to implement a leftist tree using heaps as a base class. The following is the contents of heap.h:
template <class T>
class heap {
public:
virtual void init(T*) = 0;
virtual void insert(T*) = 0;
virtual T delete_min() = 0;
};
The following is the contents of leftist.cpp:
#include "heap.h"
template <class T>
class leftist_tree : public heap<T> {
private:
T* root;
public:
void init(T* a) {}
void insert(T* a) {}
T delete_min() {T a; return a;}
};
I am passing another class leftist_node as a parameter to this class using the following definition:
leftist_tree<leftist_node> mytree;
I am getting an LNK 2001 unresolved external symbol error for functions init, insert and delete_min. What am I doing wrong?
Edit:
Okay the example I have given at this point is far too complex. I have tried to reproduce the same error on a smaller scale so that someone can identify the problem more easily. I have created the following sample files.
try.cpp
#include "stdafx.h"
#include "myclass.h"
int _tmain(int argc, _TCHAR* argv[])
{
myclass<int> a;
a.hello(3);
return 0;
}
myclass.h
template <class T>
class myclass {
public:
void hello(T);
};
myclass.cpp
#include "myclass.h"
#include <iostream>
using namespace std;
template <class T>
void myclass<T>::hello(T a){
cout<<a<<endl;
system("pause");
}
I get a similar error message:
1>try.obj : error LNK2001: unresolved external symbol "public: void __thiscall myclass::hello(int)" (?hello#?$myclass#H##QAEXH#Z)
1>c:\users\meher anand\documents\visual studio 2010\Projects\try\Debug\try.exe : fatal error LNK1120: 1 unresolved externals
Can you tell me where I am going wrong right now? Thanks
Template functions are treated a little differently from regular functions. The compiler doesn't actually compile the function until you try to use it. If the only place you try to use it is a .cpp where the body of the function is undefined, it assumes it must be compiled somewhere else and makes a reference for the linker to fill in later.
In your case you defined the body of the functions in leftist.cpp, but you didn't use it there, you used it somewhere else. If you had defined it in the .h file then the definition would have been available everywhere you tried to use it and all would be well. If you had used the functions somewhere in leftist.cpp then the functions would have been created and the linker would have fixed everything up.
The general rule is to define the body of all template functions in the header files.
The template isn't instantiated for the type. The easiest way is to remove the .cpp from being compiled, and include it into the cpp where you use the template.
Another easy answer is to just define the whole template in the .h.
Whenever you see this error
error LNK20XX unresolved external symbol
It means that while linking the linker is unable to find the function definition. In your case it is error
Hope this helps you.
Let me know if you need any more help
PK
The following should work (tested with g++):
// File: heap.hh --------------------------
template <class T>
class heap {
public:a
virtual void init(T*) = 0;
virtual void insert(T*) = 0;
virtual T delete_min() = 0;
};
// File: leftist_tree.hh ------------------
#include "heap.hh"
template <class T>
class leftist_tree : public heap<T> {
private:
T* root;
public:
void init(T* ) {}
void insert(T* ) {}
T delete_min() {T a; return a;}
};
// File: leftist_node.hh ------------------
struct leftist_node {
int value;
};
// File: leftist_main.cpp -----------------
#include "leftist_tree.hh"
#include "leftist_node.hh"
int main() {
leftist_tree< leftist_node > mytree;
}