I've been trying to create a class cartesian which objects are 2 points on the a cartesian point (int or double). Then I want to overload <<. I get the error message :
Undefined symbols for architecture x86_64:
"cartesian<double, int>::cartesian(double, int)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I dont understand where is My mistake.
THE HEADER
#include <iostream>
using namespace std;
template <class first, class second>
class cartesian
{
public:
cartesian(first, second);
//double getslope(cartesian &obj1, cartesian &obj2);
friend ostream& operator<< (ostream &out, cartesian &cPoint);
private:
first x;
second y;
};
THE CPP file
#include "cartesian.h"
#include <iostream>
using namespace std;
template<class first,class second>
cartesian<first, second>::cartesian(first a, second b)
:x(a), y(b)
{}
/*
// between obj1 and obj2
template<class first,class second>
double cartesian<first, second>::getslope(cartesian &obj1, cartesian &obj2){
return ((obj2.y-obj1.y)/(obj2.x-obj1.y));
}
*/
template<class first,class second>
ostream& operator<< (ostream &out,const cartesian<first, second> &cPoint)
{
// Since operator<< is a friend of the Point class, we can access
// Point's members directly.
out << "(" << cPoint.x << ", " <<
cPoint.y << ")";
return out;
}
THE MAIN
#include <iostream>
#include "cartesian.h"
using namespace std;
int main()
{
cartesian<double, int> ob11(3.4, 6);
return 0;
}
You need to put the implementation in the header file or in a file included by the header. The compiler needs access to the code in order to "build" the cartesian<double, int> specialization you require in main.
For example, here we put the constructor's implementation in the class declaration:
template <class first, class second>
class cartesian
{
public:
cartesian(first, second) :x(a), y(b) {}
};
It doesn't have to go inside the class declaration itself, but the code must be accessible from the header file.
Related
I'm trying to build a simple heap data structure for practice. When I build the version for double it works fine.
class heapt {
public:
heapt();
heapt(std::initializer_list<double> lst);
void print_heapt();
private:
int size;
int length;
double* elem; //points to root
};
Its constructors works perfectly and the heap is printed as it should. But when I try to generalize it with
template< typename Elem>
as:
template<typename Elem>
class heapt {
public:
heapt();
heapt(std::initializer_list<Elem> lst);
void print_heapt();
private:
int size;
int length;
Elem* elem; //points to root
};
for the class definition and as:
template<typename Elem>
heapt<Elem>::heapt(std::initializer_list<Elem> lst) :
size{ static_cast<int>(lst.size()) },
elem{new Elem[lst.size()]}
{
std::copy(lst.begin(), lst.end(), elem);//Now heaptify elem
build_heapt(elem, lst.size());
}
for one of the constructors used in the main function.
I get two linking errors:
LNK2019 unresolved external symbol "public: void __thiscall heapt::print_heapt(void)" (?print_heapt#?$heapt#H##QAEXXZ) referenced in function _main
LNK2019 unresolved external symbol "public: __thiscall heapt::heapt(class std::initializer_list)" (??0?$heapt#H##QAE#V?$initializer_list#H#std###Z) referenced in function _main
The main function is:
{
heapt<int> hh{ 27,12,3,13,2,4,14,5 };
std::cout << "Hello" << '\n';
hh.print_heapt();
}
EDIT: The heapt class is in the "heap.h" file and the definition for the constructor heapt<Elem>::heapt(std::initializer_list<Elem> lst) is in the "heap.cpp" class, which has #include"heap.h" as a header file. The int main function is in a file named "InSo.cpp", which also has #include"heap.h" as a header file.
In your templated class declaration you are using heapt(std::initializer_list<double> lst); but in your definition you are using std::initializer_list<Elem>. You should change the declaration to heapt(std::initializer_list<Elem> lst);
You are still missing definitions for print_heapt and build_heapt but otherwise it should compile.
EDIT: In light of you clarifying how your source files are set up, see WhozCraig's comment on your initial post. You can either include the definition of the templated class functions in a heap.hpp file, for example, and include it at the end of your heap.h, or just put them all together in one file, e.g.
// heap.h
#ifndef HEAP_H
#define HEAP_H
#include <initializer_list>
template<typename Elem>
class heapt {
public:
heapt();
heapt(std::initializer_list<Elem> lst);
void print_heapt();
private:
int size;
int length;
Elem* elem; //points to root
};
#include "heap.hpp"
#endif
//heap.hpp
#ifndef HEAP_HPP
#define HEAP_HPP
#include "heap.h"
#include <algorithm>
template<typename Elem>
heapt<Elem>::heapt(std::initializer_list<Elem> lst) :
size{ static_cast<int>(lst.size()) },
elem{ new Elem[lst.size()] }
{
std::copy(lst.begin(), lst.end(), elem);//Now heaptify elem
//build_heapt(elem, lst.size());
}
#endif
The problem comes from a computer graphics C++ project in which I want to calculate gradient of both scale field and 3D-vector field. We know the gradient of them are different: scale field has 3D-vector gradient while 3D-vector field has a 3x3 matrix gradient. Since all other codes are the same, I am using template to reuse code. But I met with a problem in specializing member functions which has different code for calculating gradient of different data type. The minimized code is as follows:
//======== Main.cpp ========
#include "Render.h"
int main() {}
//======== Render.cpp ========
#include "Render.h"
//======== Render.h ========
#ifndef __RENDER_H__
#define __RENDER_H__
#include "VolumeGrid.h"
#endif
//======== VolumeGrid.h ========
#ifndef __VOLUMEGRID_H__
#define __VOLUMEGRID_H__
#include "Volume.h"
template < typename U >
class _Grid {
public:
const typename GradType<U>::GType grad(const Vector& x) const;
U * values = nullptr;
};
template <>
const Vector _Grid<float>::grad(const Vector& x) const {
return Vector();
}
template <>
const Matrix _Grid<Vector>::grad(const Vector& x) const {
return Matrix();
}
#endif
//======== Volumn.h ========
#ifndef __VOLUME_H__
#define __VOLUME_H__
#include "Vector.h"
#include "Matrix.h"
template <typename U>
struct GradType {
typedef int GType;
};
template<>
struct GradType<float> {
typedef Vector GType;
};
template<>
struct GradType<Vector> {
typedef Matrix GType;
};
template< typename U >
class Volume {
public:
typedef U volumeDataType;
typedef typename GradType<U>::GType volumeGradType;
};
#endif
//======== Vector.h ========
#ifndef __VECTOR_H__
#define __VECTOR_H__
class Vector {
public:
float xyz[3] = { 0,0,0 };
};
#endif
//======== Matrix ========
#ifndef __MATRIX_H__
#define __MATRIX_H__
class Matrix {
public:
float m[3][3];
};
#endif
The error message is:
build/Debug/GNU-Linux/Render.o: In function `Vector::Vector()':
/home/CppApplication_1/VolumeGrid.h:19:
multiple definition of `_Grid<float>::grad(Vector const&) const'
build/Debug/GNU-Linux/Main.o:/home/CppApplication_1/VolumeGrid.h:19:
first defined here
build/Debug/GNU-Linux/Render.o: In function
`_Grid<Vector>::grad(Vector const&) const':
/home/CppApplication_1/VolumeGrid.h:24:
multiple definition of `_Grid<Vector>::grad(Vector const&) const'
build/Debug/GNU-Linux/Main.o:/home/CppApplication_1/VolumeGrid.h:24:
first defined here
As you can see from the code, the two specialized grad function corresponding to different data types are defined only once in VolumeGrid.h, as member function of class Grid<float> and Grid<Vector>, respectively. But the error message says there are multiple definitions of them. The code is compiled with g++ 4.8.4 with C++11 enabled on ubuntu 14.04 64-bit (it compiles well on Visual Studio 2015). The code above is minimized in that removal of any line, e.g., #include "Render.h" in Main.cpp, will make the error disappear. The header inclusion structure and class inheritance hierarchy should not be changed because they are used in actual project. So could you please tell me where is the problem in specializing the grad function and how to fix it? Thanks a lot for your help.
An explicit function template specialization (having no template parameters) is not implicitly inline like actual templates are.
Either move the definitions to a *.cpp file, or mark them inline.
If you move them to a *.cpp file, you should declare them in the header file, like
template <>
const Vector _Grid<float>::grad(const Vector& x) const;
I am trying run the following program, But it generates compilation error:
#ifndef TEMPLATE_SUM_H_
#define TEMPLATE_SUM_H_
template<typename T>
class sum
{
public:
sum() {
val_1 = 0;
val_2 = 0;
}
sum(T a, T b) {
val_1 = a;
val_2 = b;
}
friend std::ostream& operator<<(std::ostream &, const sum<> &);
private:
T val_1, val_2;
T result() const;
};
#endif
Source file:
include <iostream>
#include "inc/sum.h"
template<typename T>
T sum<T>::result() const {
return (val_1 + val_2);
}
template<typename T>
std::ostream& operator<<(std::ostream& os, const sum<T>& obj) {
//std::ostream& operator<<(std::ostream& os, sum<T>& obj) {
os << obj.result();
return os;
}
int main()
{
sum<int> int_obj(15, 15);
sum<float> float_obj(5.2, 3.5);
std::cout << "result of int = " << int_obj << std::endl;
std::cout << "result of float = " << float_obj << std::endl;
return 0;
}
Compiling with g++ (4.4.3) it generates following error:
In file included from template.cpp:2:
inc/sum.h:18: error: wrong number of template arguments (0, should be 1)
inc/sum.h:5: error: provided for ‘template<class T> class sum’
template.cpp: In function ‘std::ostream& operator<<(std::ostream&, const sum<T>&) [with T = int]’:
template.cpp:20: instantiated from here
template.cpp:5: error: ‘T sum<T>::result() const [with T = int]’ is private
template.cpp:12: error: within this context
template.cpp: In function ‘std::ostream& operator<<(std::ostream&, const sum<T>&) [with T = float]’:
template.cpp:21: instantiated from here
template.cpp:5: error: ‘T sum<T>::result() const [with T = float]’ is private
template.cpp:12: error: within this context
1) Can Anyone please help me in identifying the error ?
Also Please suggest some links where I can find brief absolute details on how to use templates in c++.
2) I read that templatized func/classes declared in header file, and defined separately are prone to linking error. Can anyone explain/elaborate this ?
Is there any possibility of linking error in above example ?
The statement is as below:
"If a template or inline function is declared in a .h file, define it in that same file. The definitions of these constructs must be included into every .cpp file that uses them, or the program may fail to link in some build configurations."
This example can be done in some more easy way, without using overloaded operator etc. But I am trying to learn/practising templates and experimenting some features.
You need to have a separate template definition for the friend function declaration:
template<typename U>
friend std::ostream& operator<<(std::ostream &, const sum<U> &);
friend declarations do not inherit the template parameters of the enclosing class.
A simple sample source, to get started;
Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
template <class TYPE>
class Calculator{
public:
Calculator();
TYPE Sum(TYPE param1, TYPE param2);
};
/**
* To avoid template related compilation error
* when templates are used in header and source files
*
* This class file has been removed from the project-source file.
* However, is present in the project folder
* Gets compiled with the header-file (being included)
*/
#include "Calculator.cpp"
#endif
Calculator.cpp
#include <iostream>
using namespace std;
#include "Calculator.h"
template <class TYPE>
Calculator<TYPE>::Calculator()
{
}
template <class TYPE>
TYPE Calculator<TYPE>::Sum(TYPE param1, TYPE param2){
cout << "Calculator::sum" << endl;
cout << param1 <<endl;
cout << param2 <<endl;
TYPE result = param1 + param2 ;
return result;
}
Main.cpp
#include <iostream>
using namespace std;
#include "Calculator.h"
int main(int argc, const char * argv[]) {
cout << "Hello, Calculator!\n";
Calculator<int> cObj;
int out = cObj.Sum(2,3);
cout << "out : " << out << endl;
Calculator<string> cObjS;
string outS = cObjS.Sum("A", "B");
cout << "outS : " << outS << endl;
cout << "Bye, Calculator!\n";
return 0;
}
Additionally, you can refer to the post, to know about how to keep the template source and header contents, and knowing about how to fix the compilation and linker issues (with reasons).
I thought that friend functions could access class variables as in how I try to do v.x, v.y, v.z in the << function. But it doesn't compile. It says it's unable to resolve identifier at those lines.
Also I'm trying to learn how to use namespaces. Even though I use the namespace vec in the implementation file I still have to include Vector:: before everything so what's the point?
Header file:
#ifndef VECTOR_H
#define VECTOR_H
namespace vec {
class Vector {
private:
double x, y, z;
public:
Vector(double, double, double);
friend std::ostream& operator<<(std::ostream&, const Vector&);
};
}
#endif /* VECTOR_H */
.cpp file:
#include "Vector.h"
#include <iostream>
using namespace vec;
//Constructor
Vector::Vector(double x1 = 0, double y1 = 0, double z1 = 0) {
x = x1;
y = y1;
z = z1;
}
//Have also tried adding vec:: and Vector:: before operator<< here.
std::ostream& operator<<(std::ostream& out, const Vector& v) {
out<<"<"<<v.x<<", "<<v.y<<", "<<v.z<<">";
return out;
}
I believe part of the problem is that your vec.h doesn't have #include <iostream>, so the type std::ostream is unidentified in that file, and since that part is compiled before the vec.cpp main part, it fails to recognise your function.
You also need to put your operator<< into the namespace of vec. After all, you have asked for a friend function within that namespace.
With these two changes, your code compiles with gcc -Wall -Wextra -O2.
Your compile error may relative to below issues:
Default parameter only goes to function declaration not function
definition, you are doing the other way around.
Also, in Vector.cpp you should wrap up your class member function
definitions in namespace instead of calling using directive.
Try:
Vector.h
#include <iostream>
class Vector {
private:
double x, y, z;
public:
Vector(double x1 = 0, double y1 = 0, double z1 = 0);
^^ ^^ ^^
friend std::ostream& operator<<(std::ostream&, const Vector&);
};
Vector.cpp
namespace vec
{
Vector::Vector(double x1, double y1, double z1)
:x(x1), y(y1), z(z1)
{
}
}
The friend std::ostream& operator<< declaration appears in namespace vec, so the definition should be prefixed by vec::. Your comment says you tried that - maybe you got confused by the other error messages billz documents, but you should reinstate vec::operator<< or surround it with namespace vec { ... }.
This creates an error like:
ns.cc: In function `int main()':
ns.cc:26: error: ambiguous overload for 'operator<<' in 'std::cout << w'
ns.cc:19: note: candidates are: std::ostream& operator<<(std::ostream&, const vec::Vec&)
ns.cc:10: note: std::ostream& vec::operator<<(std::ostream&, const vec::Vec&)
I'm trying to overload the "<<" operator for a template class. I've the definition of the class in a .h file and its implementation in a .cpp file.
/tmp/ccjJIJhO.o: In function `main':
main.cpp:(.text+0xad): undefined reference to `std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, FeatureVector<int>&)'
main.cpp:(.text+0xba): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, FeatureVector<int> const&)'
collect2: ld returned 1 exit status
The class definition:
common.h
#include <iostream>
using namespace std;
featurevector.h
#ifndef FEATURE_VECTOR_H
#define FEATURE_VECTOR_H
#include <common.h>
template < class FEAT_TYPE >
class FeatureVector;
template < class FEAT_TYPE >
istream & operator >> (istream &, FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
ostream & operator << (ostream &, const FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
class FeatureVector{
public:
FeatureVector(int = 0);
...
friend istream & operator >> <>(istream &, FeatureVector<FEAT_TYPE> & );
friend ostream & operator << <>(ostream &, const FeatureVector<FEAT_TYPE> &);
...
~FeatureVector();
private:
int m_nDim;
FEAT_TYPE * m_pFeat;
};
#endif
featurevector.cpp
#include <featurevector.h>
...
template < class FEAT_TYPE >
istream & operator >> (istream & input, FeatureVector< FEAT_TYPE> & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
input >> refFeat.m_pFeat[d];
}
return (input);
}
template < class FEAT_TYPE >
ostream & operator << (ostream & output, const FeatureVector< FEAT_TYPE > & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
output << refFeat.m_pFeat[d] << " ";
}
output << endl;
return (output);
}
...
#include "featurevector-impl.cpp"
featurevector-impl.cpp
template class FeatureVector<int>;
//template istream & operator >> <>(istream &, FeatureVector<int> &);
//template ostream & operator << <>(ostream &, const FeatureVector<int> &);
mylib.h
#ifndef MY_LIB_H
#define MY_LIB_H
#include <featurevector.h>
#endif
main.cpp
#include <mylib.h>
#include <common.h>
int main(){
FeatureVector<int> pFeat(10);
cin >> (pFeat);
cout << (pFeat);
return (0);
}
Makefile associated with "mylib"
INC=./inc
SRC=./src
LIB=./lib
OBJ=./obj
CC=g++
CFLAGS=-O3 -Wall
mylib: $(LIB)/mylib.a
echo "mylib was created!..."
$(LIB)/mylib.a: \
$(OBJ)/featurevector.o
ar csr $(LIB)/mylib.a \
$(OBJ)/featurevector.o
$(OBJ)/featurevector.o: $(SRC)/featurevector.cpp
$(CC) -c $(CFLAGS) $(SRC)/featurevector.cpp -I$(INC) \
-o $(OBJ)/featurevector.o
clean:
rm -rf $(LIB)/*.a
rm -rf $(OBJ)/*.o
Makefile for main.cpp (the main.cpp with its Makefile are under an "app" directory)
LIB=../lib
INC=../inc
OBJ=../obj
BIN=../bin
CC=g++
CFLAGS=-O3 -Wall
LFLAGS=-lmylib -lm
$#.cpp: $(LIB)/mylib.a $#.cpp
cd ..; make; cd app;
$(CC) $(CFLAGS) $#.cpp -o $(BIN)/$# -I$(INC) -L$(LIB) $(LFLAGS)
clean:
rm -rf $(BIN)/*
According to this, you have to make the function known as template in your class definition.
class.h
#include <iostream>
using std::ostream;
template <typename T>
class A {
public:
...
template <typename J> // <-- CAUTION!
friend ostream &operator<<(ostream &output, const A<J> &a);
};
class.cpp
#include "class.h"
...
template <typename T>
ostream &operator<<(ostream &output, const A<T> &a) {
// Your implementation
return output;
}
...
template ostream &operator<<(ostream &output, const A<int> &a);
template ostream &operator<<(ostream &output, const A<float> &a);
If the line template <typename J> is removed, the compilation error "underfined reference" comes.
See FAQ item 35.12 Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?.
Your posted error code says that it is operator>> that is throwing an unresolved external error, not operator<<. In addition, your code won't compile because there is no convert constructor on myClass taking an int. So you have not posted the correct code.
But this works:
#include <iostream>
using namespace std;
template < class T >
class myClass;
template < class T >
ostream & operator << (ostream &, const myClass<T> &);
template < class T >
class myClass{
public:
myClass(int) {}
friend ostream & operator << <>(ostream &, const myClass<T> &);
private:
T m_Data;
};
template < class T >
ostream & operator << (ostream & out, const myClass<T> & refClass){
out << refClass.m_Data << endl;
return (out);
}
myClass<int>;
myClass<float>;
int main(int argc, char **argv){
myClass<int> test(5);
cout << test;
return 0;
}
Don't make it so complicated:
template<class FEAT_TYPE>
struct FeatureVector {
FeatureVector(int = 0);
friend std::istream& operator>>(std::istream &s, FeatureVector &x) {
for(int d = 0; d < x.getDim(); d++) {
s >> x.m_pFeat[d];
}
return s;
}
friend std::ostream& operator<<(std::ostream &s, FeatureVector const &x) {
// since you're terminating with " " rather than separating:
copy(x.m_pFeat, x.m_pFeat + x.getDim(), ostream_iterator<FEAT_TYPE>(s, " "));
s << endl;
return s;
}
//...
featurevector-impl.cpp is incorrect. Explicit template instantiations look like this:
template class FeatureVector<int>;
Since the operators aren't members, they must also be explicitly instantiated:
template istream & operator >> <>(istream &, FeatureVector<int> &);
I don't recommend splitting up your template definitions like this, though, unless you're really keen on micromanaging which specific classes will work with your template (which kind of goes against the spirit of using a template).