Search code examples
c++boostlinker-errorsshared-ptrquantlib

Difficulties with Pointers in C++ / Linking error


When compiling my code I get the following error:

LNK2019 unresolved external symbol "public: class QuantLib::Matrix const & __cdecl SachLib::AWDCalculator::RSB(void)const " (?RSB@AWDCalculator@SachLib@@QEBAAEBVMatrix@QuantLib@@XZ) referenced in function "protected: void __cdecl SachLib::CalculationEngine_Sach::set_results(class boost::shared_ptr &)const " (?set_results@CalculationEngine_Sach@SachLib@@IEBAXAEAV?$shared_ptr@VAWDCalculator@SachLib@@@boost@@@Z)

It is found in CalculationEngine_Sach.obj in line 1.

Here is my code:

Abwicklungsdreieck and Gewichtungsfaktoren basically consists out of a Matrix and are obtained by its respective Reader. I think the names of their methods are unambiguous.

main.cpp:

#include "AbwicklungsdreieckReader.h"
#include "Abwicklungsdreieck.h"
#include "GewichtungsfaktorenReader.h"
#include "Gewichtungsfaktoren.h"
#include "Tarif_Sach.h"
#include "CalculationEngine_Sach.h"
#include "CalculationEngine_Sach_Typ1.h"


#if defined(QL_ENABLE_SESSIONS)
namespace QuantLib {
    Integer sessionId() { return 0; }
}
#endif

using namespace QuantLib;
using namespace SachLib;


int main()
{
    std::cout << "\n\n\nTest Chain-Ladder-Verfahren\n\n";

    std::string input1 = "C:/Users/D91476/Desktop/LifeLib_Sol/awd.csv";
    std::string input2 = "C:/Users/D91476/Desktop/LifeLib_Sol/gwf.csv";


    boost::shared_ptr<PricingEngine> EngineTyp1(new CalculationEngine_Sach_Typ1());

    SachLib::AbwicklungsdreieckReader input1Reader(input1);
    SachLib::GewichtungsfaktorenReader input2Reader(input2);

    SachLib::Abwicklungsdreieck AWD = input1Reader.get_awd();
    std::cout << "\nInput 1: Abwicklungsdreieck\n\n";
    std::cout << AWD.get_Matrix() << "\n";

    SachLib::Gewichtungsfaktoren GWF = input2Reader.get_gwf();
    std::cout << "\nInput 2: Gewichtungsfaktoren\n\n";
    std::cout << GWF.get_Matrix();

    Tarif_Sach *tarifsach1;
    tarifsach1 = new Tarif_Sach_Typ1(AWD, GWF);

    tarifsach1->setPricingEngine(EngineTyp1);
    EngineTyp1->calculate();
}

By testing I found out that the error appears because of the following line:

boost::shared_ptr<PricingEngine> EngineTyp1(new CalculationEngine_Sach_Typ1());

AWDCalculator.h

#pragma once

#include "Tarif_Sach.h"
#include "Abwicklungsdreieck.h"
#include "Gewichtungsfaktoren.h"

#ifndef _AWDCalculator_H
#define _AWDCalculator_H

namespace SachLib {

    class AWDCalculator {
    public:
        AWDCalculator();
        AWDCalculator(Tarif_Sach::arguments *arguments);
        AWDCalculator(Abwicklungsdreieck awd, Gewichtungsfaktoren gwf);
        AWDCalculator(const AWDCalculator &obj);
        AWDCalculator& operator=(AWDCalculator const& rhs);


        //! Fills vectors.
        void update(Tarif_Sach::arguments *arguments);

        // Logic
        void calculate(Abwicklungsdreieck awd, Gewichtungsfaktoren gwf);

        //! \name Getter
        //@{
        const Abwicklungsdreieck& awd() const;
        const Gewichtungsfaktoren& gwf() const;
        const Matrix& estimated_costs_matrix() const;
        const Matrix& RSB_all() const;
        const Matrix& RSB() const;
        //@}

        Tarif_Sach::arguments *arguments_;

    protected:
        AWDCalculator *results_;
        Abwicklungsdreieck awd_;
        Gewichtungsfaktoren gwf_;

        //!  \name Outputs
        //@{
        Matrix estimated_costs_matrix_;
        Matrix RSB_all_;
        Matrix RSB_;
        //@}

    };

}

#endif

AWDCalculator.cpp

#include "AWDCalculator.h"


SachLib::AWDCalculator::AWDCalculator()
{
}

SachLib::AWDCalculator::AWDCalculator(Tarif_Sach::arguments *arguments)
    : AWDCalculator(arguments->awd, arguments->gwf)
{
    arguments_ = arguments;
}

SachLib::AWDCalculator::AWDCalculator(Abwicklungsdreieck awd, Gewichtungsfaktoren gwf)
    : awd_(awd),
    gwf_(gwf)
{
    results_ = new AWDCalculator(awd, gwf);
    calculate(awd, gwf);
}

SachLib::AWDCalculator::AWDCalculator(const AWDCalculator& obj)
{
    arguments_ = obj.arguments_;
    awd_ = obj.awd_;
    gwf_ = obj.gwf_;
}

SachLib::AWDCalculator& SachLib::AWDCalculator::operator=(AWDCalculator const& rhs)
{
    arguments_ = rhs.arguments_;
    awd_ = rhs.awd_;
    gwf_ = rhs.gwf_;

    return *this;
}


void SachLib::AWDCalculator::update(Tarif_Sach::arguments *arguments)
{
    results_ = new AWDCalculator(arguments);
    arguments_ = arguments;
    awd_ = arguments->awd;
    gwf_ = arguments->gwf;
}

void SachLib::AWDCalculator::calculate(Abwicklungsdreieck awd, Gewichtungsfaktoren gwf)
{
    // RSB_, RSB_all_ and estimated_costs_matrix_ get calculated here with the input awd and gwf
}

inline const Matrix& SachLib::AWDCalculator::estimated_costs_matrix() const
{
    return estimated_costs_matrix_;
}

inline const Matrix& SachLib::AWDCalculator::RSB_all() const
{
    return RSB_all_;
}

inline const Matrix& SachLib::AWDCalculator::RSB() const
{
    return RSB_;
}

inline const SachLib::Abwicklungsdreieck& SachLib::AWDCalculator::awd() const
{
    return awd_;
}

inline const SachLib::Gewichtungsfaktoren& SachLib::AWDCalculator::gwf() const
{
    return gwf_;
}

CalculationEngine_Sach.h

#pragma once

#ifndef SachLib_calculationengine_sach_hpp
#define SachLib_calculationengine_sach_hpp

#include "Tarif_Sach.h"
#include "AWDCalculator.h"

using namespace QuantLib;

namespace SachLib {

    class CalculationEngine_Sach : public Tarif_Sach::engine {
    public:
        CalculationEngine_Sach();
        void calculate() const;

    protected:
        mutable boost::shared_ptr<AWDCalculator> AWDCalculator_;

        void set_results(boost::shared_ptr<AWDCalculator> &awdCalculator) const;

    };

}

#endif

CalculationEngine_Sach.cpp

#include "CalculationEngine_Sach.h"
#include "Tarif_Sach.h"
#include "AWDCalculator.h"


using namespace QuantLib;

namespace SachLib {

    CalculationEngine_Sach::CalculationEngine_Sach()
    {

    }

    void CalculationEngine_Sach::calculate() const
    {
        arguments_.AWDCalculator->update(&arguments_);

        CalculationEngine_Sach::set_results(arguments_.AWDCalculator);
    }

    void CalculationEngine_Sach::set_results(boost::shared_ptr<AWDCalculator> &awdCalculator) const
    {
        results_.estimated_costs_matrix = awdCalculator->estimated_costs_matrix();
        results_.RSB_all = awdCalculator->RSB_all();
        results_.RSB = awdCalculator->RSB();
        // because of the above three lines the error appears
    }
}

CalculationEngine_Sach_Typ1.h

#pragma once
#include "CalculationEngine_Sach.h"

namespace SachLib {
    class CalculationEngine_Sach_Typ1 : public CalculationEngine_Sach
    {
    public:
        CalculationEngine_Sach_Typ1();
    };

}

CalculationEngine_Sach_Typ1.cpp

#include "CalculationEngine_Sach_Typ1.h"

SachLib::CalculationEngine_Sach_Typ1::CalculationEngine_Sach_Typ1()
{}

If anyone could help I'd be much grateful.


Solution

  • You marked that function inline in the .cpp:

    inline const Matrix& SachLib::AWDCalculator::RSB() const
    

    In this case the compiler does not have to generate an out-of-line definition, unless it is needed in that translation unit (e.g. function address is taken). And that causes the linker error.

    Remove inline from the function definition to make the compiler generate an out-of-line definition to fix the linker error.