Template issues in C++ - c++

The issue I'm having here is class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Sadrzaj const &). I have searched far and wide on the Internet for a solution but could not find it. The issue occurs when I try to include Data.h in the main source file, the same happens with Content.h. Down below are the two header files for reference. Any help whatsoever is greatly appreciated. :-)
#pragma once
#include <iostream>
class Content
{
friend std::ostream& operator<<(std::ostream &str, const Content&);
public:
virtual void print(std::ostream&) const = 0;
};
std::ostream& operator<<(std::ostream &str, const Content& temp)
{
temp.print(str);
return str;
}
#pragma once
#include "Content.h"
template <class T>
class Data: public Content
{
public:
Data(const T&);
void print(std::ostream&) const override;
private:
T data;
};
template <class T>
Data<T>::Data(const T& data) : data(data) {}
template <class T>
void Data<T>::print(std::ostream& str) const { str << data; }

Okay, so the problem was that the << operator was defined in the "Content.h" header file. Simply by creating a new source file "Content.cpp" and defining it there, the problem was solved. If anyone knows why this solved the error, I would appreciate it very much if they would explain it to me, so that I don't make the same mistake again. :-)

Related

Compilation Error About Templated Classes [duplicate]

This question already has answers here:
Undefined reference to destructor error in c++?
(2 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 11 months ago.
I have a AVL class like this, it's templated and it gives error in main, I have tried to debug it for hours but it didn't fixed. What can be the problem? What part am I missing? It can be related to constructors but I tried that and it didn't fixed. I'm using Visual Studio 2012 and I feel stuck.
The error is:
1>Ege_HW2.obj : error LNK2019: unresolved external symbol "public: __thiscall AvlTree<struct item>::~AvlTree<struct item>(void)" (??1?$AvlTree#Uitem####QAE#XZ) referenced in function __unwindfunclet$??0AVLSection##QAE#XZ$0
1>Ege_HW2.obj : error LNK2019: unresolved external symbol "public: __thiscall AvlTree<struct AVLSection>::~AvlTree<struct AVLSection>(void)" (??1?$AvlTree#UAVLSection####QAE#XZ) referenced in function _main
1>fatal error LNK1120: 2 unresolved externals
Header file:
#ifndef AVLTREE_H
#define AVLTREE_H
#include <iostream>
#include <string>
using namespace std;
/* AVL Tree is taken from the lecture slides. */
template <class Comparable>
class AvlTree;
template <class Comparable>
class AvlNode
{
Comparable element;
AvlNode* left;
AvlNode* right;
int height;
AvlNode(const Comparable& theElement,
AvlNode* lt, AvlNode* rt, int h = 0)
: element(theElement), left(lt), right(rt), height(h) { }
friend class AvlTree<Comparable>;
};
template <class Comparable>
class AvlTree
{
public:
explicit AvlTree();
explicit AvlTree(const Comparable& notFound);
AvlTree(const AvlTree& rhs);
~AvlTree();
const Comparable& findMin() const;
const Comparable& findMax() const;
const Comparable& find(const Comparable& x) const;
bool isEmpty() const;
void printTree() const;
void makeEmpty();
void insert(const Comparable& x);
void remove(const Comparable& x);
const AvlTree& operator=(const AvlTree& rhs);
private:
AvlNode<Comparable>* root;
const Comparable ITEM_NOT_FOUND;
const Comparable& elementAt(AvlNode<Comparable>* t) const;
void insert(const Comparable& x, AvlNode<Comparable>*& t) const;
void remove(const Comparable& x, AvlNode<Comparable>*& t) const;
AvlNode<Comparable>* findMin(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* findMax(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* find(const Comparable& x, AvlNode<Comparable>* t) const;
void makeEmpty(AvlNode<Comparable>*& t) const;
void printTree(AvlNode<Comparable>* t) const;
AvlNode<Comparable>* clone(AvlNode<Comparable>* t) const;
// Avl manipulations
int height(AvlNode<Comparable>* t) const;
int max(int lhs, int rhs) const;
void rotateWithLeftChild(AvlNode<Comparable>*& k2) const;
void rotateWithRightChild(AvlNode<Comparable>*& k1) const;
void doubleWithLeftChild(AvlNode<Comparable>*& k3) const;
void doubleWithRightChild(AvlNode<Comparable>*& k1) const;
};
#include "AvlTree.cpp"
#endif
Cpp file:
#include "avlTree.h"
#include <iostream>
using namespace std;
template <class Comparable>
AvlTree<Comparable>::AvlTree(){
root = NULL;
}
/*** Construct the tree.
*/
template <class Comparable>
AvlTree<Comparable>::AvlTree(const Comparable& notFound)
:ITEM_NOT_FOUND(notFound), root(NULL){}
/*** Copy constructor.*/
template <class Comparable>
AvlTree<Comparable>::AvlTree(const AvlTree<Comparable>& rhs)
: root(NULL), ITEM_NOT_FOUND(rhs.ITEM_NOT_FOUND) {
*this = rhs;
}
And finally the main:
#include <iostream>
#include <string>
#include "BinaryTree.h"
#include "AvlTree.h"
#include <fstream>
using namespace std;
struct item{
string title;
string information;
item(){};
};
struct AVLSection{
AvlTree<item> avlSection;
string sectionTitle;
AVLSection(){};
};
struct BSTSection{
BinarySearchTree <item> bstSection;
string sectionTitle;
BSTSection(){}
};
void readData(BinarySearchTree<BSTSection> & bst, AvlTree<AVLSection> & avl){
ifstream input;
string filename = "data.txt",line;
input.open(filename.c_str());
while(getline(input,line)){
cout << line;
}
}
int main(){
BinarySearchTree<BSTSection> bst;
AvlTree<AVLSection> avl;
}

C++ redefinition error, Why am I getting this error?

I had a redefinition problem but I noticed that I already included .cpp file in the .hpp file so my mistake was including the .hpp file in my .cpp file again
Now I am getting this error, something to do with templates.
Also while you fix my problem, can you explain to me what template class does?
cplusplus.com is not that descriptive.
Thank you. :)
//implementation
template<class T>
ArrayBag<T>::ArrayBag() : item_count_(0){}
-------------WARNING YOU ARE NOW LEAVING IMPLEMENTATION---------------------------
//interface
#ifndef ARRAY_BAG_H
#define ARRAY_BAG_H
#include <vector>
template<class T>
class ArrayBag
{
protected:
static const int DEFAULT_CAPACITY = 200;
T items_[DEFAULT_CAPACITY];
int item_count_;
int get_index_of_(const T& target) const;
public:
ArrayBag();
int getCurrentSize() const;
bool isEmpty() const;
//adds a new element to the end, returns true if it was successfully been added
bool add(const T& new_entry);
bool remove(const T& an_entry);
void clear();
bool contains(const T& an_entry) const;
int getFrequencyOf(const T& an_entry) const;
std::vector<T> toVector() const;
void display() const;
//overloading operators for objects
void operator+=(const ArrayBag<T>& a_bag);
void operator-=(const ArrayBag<T>& a_bag);
void operator/=(const ArrayBag<T>& a_bag);
};
#include "ArrayBag.cpp"
#endif
-------------WARNING YOU ARE NOW LEAVING INTERFACE---------------------------
//error
5 C:\Users\minahnoona\Desktop\ArrayBag.cpp expected constructor, destructor, or type conversion before '<' token
5 C:\Users\minahnoona\Desktop\ArrayBag.cpp expected `;' before '<' token
Don't call your ArrayBag.cpp a .cpp file. Template implementations go in header files, and the name should reflect that.
If you want the implementation in a separate file (you don't strictly need to), call it ipp or tpp. Something the project system won't try to compile on its own.
Then include it from the .hpp and don't include the .hpp from the .ipp.

C++: Derive a class template from QuantLib::PiecewiseYieldCurve

I would like to derive a class template from QuantLib::PiecewiseYieldCurve. This is my derived class definition:
#include <ql\termstructures\yield\piecewiseyieldcurve.hpp>
#include <MarKetQuote\include\OISQuote.h>
#include <vector>
using namespace QuantLib;
/*! \brief Class to bootstrap an OIS curve.
*/
template <class Traits, class Interpolator,
template <class> class Bootstrap = IterativeBootstrap>
class OISCurve : public PiecewiseYieldCurve < Traits, Interpolator, Bootstrap >
{
private:
/** Typedef to refer to the specialized class.
It was necessary to add it in other to be able to declare the constructor as in QuantLib::PiecewiseYieldCurve.
*/
typedef OISCurve<Traits, Interpolator, Bootstrap> this_ois_curve;
public:
/** Constructor.
*/
OISCurve(
const Date& referenceDate,
const std::vector<OISQuote>& quotes,
const DayCounter& dayCounter,
Real accuracy,
const Interpolator& i = Interpolator(),
const Bootstrap<this_ois_curve>& bootstrap = Bootstrap<this_ois_curve>());
};
OISQuote is simply a class derived from QuantLib::SimpleQuote. I'm not familiar with this type of complicated templating, but to my limited understanding the above should be ok. It compiles actually. The problem arises when I try to instantiate a specialized class like this:
OISCurve<Discount, LogLinear> oisCurve = OISCurve<Discount, LogLinear>(Date::todaysDate(), quotes, Actual360(), 1.0e-12);
I get a linking error LNK2019 (using visual studio):
main.obj : error LNK2019: unresolved external symbol "public: __cdecl OISCurve<struct QuantLib::Discount,class QuantLib::LogLinear,class QuantLib::IterativeBootstrap>::OISCurve<struct QuantLib::Discount,class QuantLib::LogLinear,class QuantLib::IterativeBootstrap>(class QuantLib::Date const &,class std::vector<class OISQuote,class std::allocator<class OISQuote> > const &,class QuantLib::DayCounter const &,double,class QuantLib::LogLinear const &)" (??0?$OISCurve#UDiscount#QuantLib##VLogLinear#2#VIterativeBootstrap#2###QEAA#AEBVDate#QuantLib##AEBV?$vector#VOISQuote##V?$allocator#VOISQuote###std###std##AEBVDayCounter#2#NAEBVLogLinear#2##Z) referenced in function main
1>C:\Users\u8998\PricingEngine\build\Debug\main.exe : fatal error LNK1120: 1 unresolved externals
Thanks for the help.
EDIT:
Sorry for the late reply. Thank you #LuigiBallabio and #StudentT for your answers. My problem ended up being caused by my inexperience with class templates. I had my declaration in a header file and my implementation in a cpp file exactly as with any other class. Following the guidelines in the accepted answer of this question I modified my code accordingly:
OISCurve.h
#ifndef OIS_CURVE_H
#define OIS_CURVE_H
#include <ql\termstructures\yield\piecewiseyieldcurve.hpp>
#include <ql\termstructures\yield\ratehelpers.hpp>
#include <ql\quote.hpp>
#include <vector>
#include <boost\shared_ptr.hpp>
using namespace QuantLib;
template <class Traits, class Interpolator,
template <class> class Bootstrap = IterativeBootstrap>
class OISCurve : public PiecewiseYieldCurve < Traits, Interpolator, Bootstrap >
{
public:
OISCurve(const Date& referenceDate,
const std::vector<boost::shared_ptr<Quote>>& quotes,
const DayCounter& dayCounter,
Real accuracy);
friend std::vector<boost::shared_ptr<RateHelper>> getRateHelpers(const std::vector<boost::shared_ptr<Quote>>& quotes);
private:
std::vector<boost::shared_ptr<Quote>> quotes_;
};
#include <CurveBootstrapping\src\OISCurve.cpp>
#endif
OISCurve.cpp
#include "OISCurve.h"
#include <ql\errors.hpp>
#include <algorithm>
#include <boost\foreach.hpp>
#include <ql\termstructures\yield\oisratehelper.hpp>
#include <MarKetQuote\include\OISQuote.h>
#include <ql\handle.hpp>
#include <ql\indexes\ibor\eonia.hpp>
#ifndef OIS_CURVE_IMPL
#define OIS_CURVE_IMPL
template <class T, class I, template <class> class B>
OISCurve<T, I, B>::OISCurve(
const Date& referenceDate,
const std::vector<boost::shared_ptr<Quote>>& quotes,
const DayCounter& dayCounter,
Real accuracy)
: PiecewiseYieldCurve < T, I, B >(referenceDate,
initializeQuotesAndGetRateHelpers(quotes),
dayCounter,
accuracy)
{
std::cout << "constructor works" << std::endl;
}
std::vector<boost::shared_ptr<RateHelper>> getRateHelpers(const std::vector<boost::shared_ptr<Quote>>& quotes)
{
QL_REQUIRE(std::all_of(quotes.begin(), quotes.end(), [](boost::shared_ptr<Quote> quote){ return boost::dynamic_pointer_cast<OISQuote>(quote) != 0; }),
"All quotes must be OISQuotes!");
std::vector<boost::shared_ptr<RateHelper>> rateHelpers;
BOOST_FOREACH(boost::shared_ptr<Quote> quote, quotes)
{
rateHelpers.push_back(boost::shared_ptr<RateHelper>(new OISRateHelper(2,
boost::dynamic_pointer_cast<OISQuote>(quote)->tenor(),
Handle<Quote>(quote),
boost::shared_ptr<OvernightIndex>(new Eonia()))));
}
return rateHelpers;
}
#endif
This is the solution i liked the most.
I don't think this questions relates to quantitative finance at all, but I'll answer anyway.
You have not provided an implementation to the constructor of the class OISCurve.
To link your program, do this:
OISCurve(
const Date& referenceDate,
const std::vector<OISQuote>& quotes,
const DayCounter& dayCounter,
Real accuracy,
const Interpolator& i = Interpolator(),
const Bootstrap<this_ois_curve>& bootstrap = Bootstrap<this_ois_curve>())
: <Call Parent Constructor>
{
}
You will need to replace with a call to an actual constructor defined in PiecewiseYieldCurve. There are six such constructors, so you will need to select the one that you think most appropriate. Please note that you will need to give the parent constructor a list of instruments, but it's missing in your constructor definition.

C++11 vector of shared_ptr template

I am trying to call the following function template:
template<typename T>
bool select(const std::string& ddbbName,
const std::string& sql,
std::vector<std::shared_ptr<T>>& vResultSet,
SqlErrorInfo& errorInfo);
which is defined in a class whose name is SQLite3Manager. In the following code this "select" method does nothing (a part from returning "true"). I have tried to simplify the problem description, because the problem seems to be related to the way I am calling/using/defining that method.
So the main.cpp code is:
main.cpp
#include <iostream>
#include "ES.h"
#include "SQLiteMgr.h"
int main(int argc, const char * argv[])
{
// To get an instance of the singleton
Cucut::SQLite3Manager& _sqliteMgr = Cucut::SQLite3Manager::getInstance();
std::string ddbbName("Cucut.db");
std::string sql("SELECT * FROM ES");
std::vector<std::shared_ptr<Cucut::ES>> vspEs;
Cucut::SqlErrorInfo sqlErrorInfo;
// Call the template method for <Cucut::ES> using the instance of the singleton
bool result = _sqliteMgr.select<Cucut::ES>(ddbbName, sql, vspEs, sqlErrorInfo);
return result;
}
but I get the following link error in Xcode 5:
Undefined symbols for architecture x86_64:
"bool Cucut::SQLite3Manager::select<Cucut::ES>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<std::__1::shared_ptr<Cucut::ES>, std::__1::allocator<std::__1::shared_ptr<Cucut::ES> > >&, Cucut::SqlErrorInfo&)", 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)
The full code is:
ES.h file:
#ifndef __TestSharedPtr__ES__
#define __TestSharedPtr__ES__
#include <iostream>
namespace Cucut
{
class ES
{
public:
ES();
const unsigned int& getId() const;
void setId(const unsigned int& id);
private:
unsigned int _id;
};
}
#endif /* defined(__TestSharedPtr__ES__) */
ES.cpp file:
#include "ES.h"
namespace Cucut
{
ES::ES() :
_id(0)
{
}
const unsigned int& ES::getId() const
{
return _id;
}
void ES::setId(const unsigned int& id)
{
_id = id;
}
}
SQLiteMgr.h file:
#ifndef __TestSharedPtr__SQLiteMgr__
#define __TestSharedPtr__SQLiteMgr__
#include <iostream>
#include <vector>
#include <memory>
namespace Cucut
{
struct SqlErrorInfo
{
int rc;
std::string description;
};
class SQLite3Manager
{
private:
SQLite3Manager();
SQLite3Manager(const SQLite3Manager& rs);
SQLite3Manager(SQLite3Manager&& rs);
SQLite3Manager& operator = (const SQLite3Manager& rs);
SQLite3Manager& operator = (SQLite3Manager&& rs);
public:
static SQLite3Manager& getInstance();
template<typename T>
bool select(const std::string& ddbbName,
const std::string& sql,
std::vector<std::shared_ptr<T>>& vResultSet,
SqlErrorInfo& errorInfo);
};
}
#endif /* defined(__TestSharedPtr__SQLiteMgr__) */
And finally the SQLiteMgr.cpp file:
#include <memory>
#include <vector>
#include "SQLiteMgr.h"
namespace Cucut
{
SQLite3Manager::SQLite3Manager()
{
}
SQLite3Manager& SQLite3Manager::getInstance()
{
static SQLite3Manager instance;
return instance;
}
template<typename T>
bool SQLite3Manager::select(const std::string& ddbbName,
const std::string& sql,
std::vector<std::shared_ptr<T>>& vResultSet,
SqlErrorInfo& errorInfo)
{
return true;
}
}
Do not be distract with the name "SqliteMgr" because in the aforementioned example I have removed any kind of reference to sqlite3 in order to simplify the problem; so, it seems that I am not calling or defining the method "select" in the correct way because I get the aforementioned link error.
Any help will be appreciated. Thanks in advance.
Function template definitions must always be in the header file so that code can be generated at the point of instantiation (here in main). If you don't do this, the compiler will expect you to manually instantiate the template, which is why there is a linker error. Move the body of the select function to SQLiteMgr.h and it will work.

overloading << for my class

I'm trying to write the global function:
std::ostream& operator<<(std::ostream& out, const Str& str)
{
for(int i = 0; i < (int)str.mSize; ++i)
out << str.mBuffer[i];
return out;
}
For a custom string class. It compiles fine but when I go to link:
1>Str.obj : error LNK2005: "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Str const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABVStr###Z) already defined in Main.obj
1>C:\Users\Ron\Documents\Visual Studio 2010\Projects\App\Debug\App.exe : fatal error LNK1169: one or more multiply defined symbols found
How could multiple definitions for this exist? I just created the class Str.
I think you have defined twice in Main.cpp and Str.cpp, or may be .h files.
Write a str.h files which include the declaration of the Str class:
//str.h
class Str {
// your class stuff
friend std::ostream& operator<<(std::ostream& out, const Str& str);
};
then in str.cpp:
//str.cpp
#include "str.h"
std::ostream& operator<<(std::ostream& out, const Str& str) {
for(int i = 0; i < (int)str.mSize; ++i)
out << str.mBuffer[i];
return out;
}
Then you can use the function in you main.cpp.
If you define a function in a header file and include it twice, you'll get a multiple definition error, which you have.
To remedy this, declare the function in the header with a prototype and define it in a .cpp file.
Alternately, if you're trying to make a header only library, you could do
class Str {
// your class stuff
friend std::ostream& operator<<(std::ostream& out, const Str& str) {
for(int i = 0; i < (int)str.mSize; ++i)
out << str.mBuffer[i];
return out;
}
};
Did you put this in a header file?
The right way to do it is to declare it in the header file and put the code in a source file.