dimanche 13 janvier 2019

Random number generator class - access functions to generator don't work

I am relatively new to C++ and I am having an issue with a very useful random number generator class that I programmed thanks to stackoverflow. I am using MS Visual Studio running on Windows 10. The original version works very well, but I would like to add two access functions: Get_Generator and Set_Generator. However, no matter how I try to do this I obtain the link error shown below. I am confused since I copied the format of the other, working member functions when I wrote these member functions. I'm sure I am making a simple mistake, but I cannot find anything online that will shed light onto my error. My apologies for the long code but I thought it important to see the full class definition(s) and the member functions.

Thanks for your time!

// Random_Num.h


#ifndef RANDOM_NUM_H
#define RANDOM_NUM_H

#ifdef _MSC_VER
#pragma once
#endif  // _MSC_VER

#include <cstdlib>                                                                  // standard Library
#include <random>                                                                   // required for random number generation
#include <ctime>                                                                    // to seed the generator with the clock
#include <chrono>                                                                   // to seed the generator with the clock

//
// User Interface
//

class IRandom
{
public:

    virtual double Ran_D() = 0;                                                     // random double on [0.0, 1.0)

    virtual double Ran_D(double minValue, double maxValue) = 0;                     // random double on [minValue, maxValue)

    virtual long long int Ran_I(long long int maxValue) = 0;                        // random integer on [0, maxValue]

    virtual long long int Ran_I(long long int minValue,                             // random integer on [minValue, maxValue]
        long long int maxValue) = 0;

    virtual std::mt19937 Get_Generator() = 0;                                       // Access function [minValue, maxValue]

    virtual void Set_Generator(std::mt19937 G) = 0;                                 // access function

};

// random number generation class, also in Random_Num.h

class Random_Num : public IRandom
{
private:

    std::mt19937 _randomNumberGenerator;
    std::uniform_real_distribution<double> _realDistribution;

public:

    Random_Num(long long int seed);                                                 // constructor - initalize Mercent Twist enginge

    virtual ~Random_Num();                                                          // default destructor

    double Ran_D();                                                                 // random double on [0,1)

    double Ran_D(double minValue, double maxValue);                                 // random double on [minValue,maxValue)

    long long int Ran_I(long long int maxValue);                                    // random integer on [0, maxValue]

    long long int Ran_I(long long int minValue, long long int maxValue);            // random integer on [minValue, maxValue]

    std::mt19937 Get_Generator();                                                   // Access function [minValue, maxValue]

    void Set_Generator(std::mt19937 G);                                             // access function

};

#endif

// Random_Num.cpp

#include "pch.h"
#include "Random_Num.h"

Random_Num::Random_Num(long long int seed)                              // constructor - initalize Mercent Twist enginge
{
    this->_randomNumberGenerator = std::mt19937((long long int) seed);
    this->_realDistribution = std::uniform_real_distribution<double>();
}

Random_Num::~Random_Num() { }                                       // default destructor


double Random_Num::Ran_D()                                      // random double on [0,1)
{
    return this->_realDistribution(_randomNumberGenerator);
}


double Random_Num::Ran_D(double minValue, double maxValue)                      // random double on [minValue,maxValue)
{
    std::uniform_real_distribution<double> distribution(minValue, maxValue);
    return distribution(this->_randomNumberGenerator);
}


long long int Random_Num::Ran_I(long long int maxValue)                         // random integer on [0, maxValue]
{
    return this->Ran_I(0, maxValue);
}


long long int Random_Num::Ran_I(long long int minValue, long long int maxValue) // random integer on [minValue, maxValue]
{
    std::uniform_int_distribution<long long int> distribution(minValue, maxValue);
    return distribution(this->_randomNumberGenerator);
}

std::mt19937 Random_Num::Get_Generator()                                // access function
{
    return this->Random_Num::_randomNumberGenerator;
}

void Random_Num::Set_Generator(std::mt19937 G)                              // access function
{
    this->Random_Num::_randomNumberGenerator = G;
}

// Main.cpp

long long int seed = (long long int) std::chrono::system_clock::now().time_since_epoch().count();
extern unique_ptr<IRandom> randomService = make_unique<Random_Num>(seed);  // make random number generator a global variable

int main(int argc, char *argv[])
{

    extern unique_ptr<IRandom> randomService;
    std::mt19937 Gen;
    double r;
    long long int i;

    r = randomService->Ran_D(); // returns random double on [0,1) - works fine
    i = randomService->Ran_I(5);    // returns random integer on [0,5] - works fine


    Gen = randomService->IRandom::Get_Generator();  // Linker error
    randomService->IRandom::Set_Generator(Gen);     // Linker error

}

// Link error

error LNK2001: unresolved external symbol "public: virtual void __cdecl IRandom::Set_Generator(class std::mersenne_twister_engine<unsigned int,32,624,397,31,2567483615,11,4294967295,7,2636928640,15,4022730752,18,1812433253>)" (?Set_Generator@IRandom@@UEAAXV?$mersenne_twister_engine@I$0CA@$0CHA@$0BIN@$0BP@$0JJAILANP@$0L@$0PPPPPPPP@$06$0JNCMFGIA@$0P@$0OPMGAAAA@$0BC@$0GMAHIJGF@@std@@@Z)

error LNK2001: unresolved external symbol "public: virtual class std::mersenne_twister_engine<unsigned int,32,624,397,31,2567483615,11,4294967295,7,2636928640,15,4022730752,18,1812433253> __cdecl IRandom::Get_Generator(void)" (?Get_Generator@IRandom@@UEAA?AV?$mersenne_twister_engine@I$0CA@$0CHA@$0BIN@$0BP@$0JJAILANP@$0L@$0PPPPPPPP@$06$0JNCMFGIA@$0P@$0OPMGAAAA@$0BC@$0GMAHIJGF@@std@@XZ)

1>C:\Users\Bill2\source\repos\qcd\x64\Release\qcd.exe : fatal error LNK1120: 2 unresolved externals
1>Done building project "qcd.vcxproj" -- FAILED.




Aucun commentaire:

Enregistrer un commentaire