0

so I have a Date Class, and each Date object stores a day, month, and year variable for the object. I also have a data file with multiple dates, many duplicate dates, and all with their own value for a float.

I am trying to store all my dates into a multimap as the key, so i can have all my duplicate dates with their floats in there too. My goal, is that I want a user to be able to enter a month and a year, and then I search my map for values with that month and year in the date object, and return the speeds for those objects. However, I get this error:

 error: no matching function for call to 'make_pair(Date&, float)'|

for this declaration

mapOption1.insert(make_pair<Date, float>(windlog[x].d, windlog[x].speed.GetSpeed()));

I don't understand why, as when I use windlog[x].d (where windlog is a vector of a struct, and d is the date object it holds at position x) in Binary Search Tree, I did not need a Get Method to store the objects in the BST. Why would I need it now? Assuming that is the issue.

Here is the code with my problem:

multimap<Date, float> mapOption1;

    for(int x = 0; x < SIZE; x++)
    {
        mapOption1.insert(make_pair<Date, float>(windlog[x].d, windlog[x].speed.GetSpeed()));
    }

Minimal reproducible example:

multimap<Date, float> mapOption1;

    Date datetest;
    datetest.SetDay("20");
    datetest.SetMonth("3");
    datetest.SetYear("2014");

    for(int x = 0; x < SIZE; x++)
    {
        mapOption1.insert(make_pair<Date, float>(datetest, 47.5);
    }

Date.h:

#if !defined(_DATE_H)
#define _DATE_H

#include <iostream>
#include <string>
#include <tuple>

using namespace std;

    /**
     * @class Date
     * @brief  Manages and holds all dates
     *
     * This class is used to convert string from the input file into numerical values
     * and then store them as date values
     * @author Darren Fernando
     *
     * @date 05/05/2020 Darren Fernando, Started
     * @bug No bugs founds as of yet
     */
class Date
{
public:
    Date();
    Date(unsigned day1, unsigned month1, unsigned year1);

        /**
        * @brief A set method that is used to set the day value
        * It takes a string parameter and calls another method to convert it, and then assign it to the variable day
        * @param day1 - A string variable that is converted
        * @return void
        */
    void SetDay(string day1);

        /**
        * @brief A set method that is used to set the month value
        * It takes a string parameter and calls another method to convert it, and then assign it to the variable month
        * @param month1 - A string variable that is converted
        * @return void
        */
    void SetMonth(string month1);

        /**
        * @brief A set method that is used to set the year value
        * It takes a string parameter and calls another method to convert it, and then assign it to the variable year
        * @param year - A string variable that is converted
        * @return void
        */
    void SetYear(string year1);

        /**
        * @brief A get method that is used to get the day value by returning it
        * @return unsigned
        */
    unsigned GetDay() const;

        /**
        * @brief A get method that is used to get the month value by returning it
        * @return unsigned
        */
    unsigned GetMonth() const;

        /**
        * @brief A get method that is used to get the year value by returning it
        * @return unsigned
        */
    unsigned GetYear() const;

        /**
        * @brief A method that converts a string to an unsigned numerical value
        * @param time - A string parameter that is converted
        * @return unsigned
        */
    unsigned convertString(string date) const;

        /**
        * @brief A method that takes an input stream and perfoms some operations to set the date from this stream
        * This method isn't used but may be valuable later on
        * @param input - An input stream
        * @return void
        */
    void SetDate(istream &input);

        /**
        * @brief A method that takes an output stream and outputs it
        * This method isn't used but may be valuable later on
        * @param os - An output stream
        * @return void
        */
    void GetDate(ostream & os) const;
    unsigned GetDateRaw() const;

private:

    int day; /// Variable to store the day
    int month; /// Variable to store the month
    int year; /// Variable to store the year

};

bool operator==(const Date& firstDate, const Date& secondDate);
bool operator>(const Date& firstDate, const Date& secondDate);
bool operator!=(const Date& firstDate, const Date& secondDate);
ostream & operator <<(ostream & os, const Date & D); /// Operator << overload
istream & operator >>(istream & input, Date & D); /// Operator >> overload
#endif  //_DATE_H

Date.cpp:

//
//
//  Generated by StarUML(tm) C++ Add-In
#include "Date.h"

    // Default constructor
Date::Date(){}

    /* Date constructor to initialize an object of date with the passed parameters
    */
Date::Date(unsigned day1, unsigned month1, unsigned year1) {

    day = day1;
    month = month1;
    year = year1;

}

void Date::SetDay(string day1) {

    day = convertString(day1); // Calls method convertString to convert the string parameter and assign the new value to day.

}

void Date::SetMonth(string month1) {

    month = convertString(month1); // Calls method convertString to convert the string parameter and assign the new value to month.

}

void Date::SetYear(string year1) {

    year = convertString(year1); // Calls method convertString to convert the string parameter and assign the new value to year.

}

unsigned Date::GetDay() const {

    return day; // Returns the day of the object

}

unsigned Date::GetMonth() const {

    return month; // Returns the month of the object

}

unsigned Date::GetYear() const {

    return year; // Returns the year of the object

}

    /* This method is used for directly setting the date from a file. It is not used now,
    but may prove handy in the future.*/
void Date::SetDate(istream &input){

    string day1;
    string month1;
    string year1;


    getline(input, day1, '/'); //Reads line until '/' is found and stores the string in day1
    getline(input, month1, '/'); //Reads line until '/' is found and stores the string in month1
    getline(input, year1, ' '); //Reads line until ' ' is found and stores the string in year1

    /*Sets the strings with setters which convert them automatically
    */
    SetDay(day1);
    SetMonth(month1);
    SetYear(year1);


}
    //This method is designed to convert a string to an integer
inline unsigned Date::convertString(string date) const{

    int date2 = 0;

    date2 = stoi(date); //Uses stoi from cmath library to convert a string to an integer

    return date2;

}

    // A get function that uses the overloaded output stream to output the date in a specific format.
void Date::GetDate(ostream &os) const{

    os << GetDay() << "/" << GetMonth() << "/" << GetYear() << " ";

}

unsigned Date::GetDateRaw() const{

    return month && year;

}

bool operator==(const Date& firstDate, const Date& secondDate)
{
    if(firstDate.GetYear() == secondDate.GetYear() && firstDate.GetMonth() == secondDate.GetMonth() && firstDate.GetDay() == secondDate.GetDay())
    {

        return true;

    }
    else
    {
        return false;
    }

}

/*bool operator!=(const Date& firstDate, const Date& secondDate)
{
    if(firstDate!=secondDate)
    {
        return true;
    }
    return false;
}*/

bool operator>(const Date& firstDate, const Date& secondDate)
{
    if(firstDate.GetYear() > secondDate.GetYear())
    {
        return true;
    }
    if(firstDate.GetYear() == secondDate.GetYear())
    {
        if(firstDate.GetMonth() > secondDate.GetMonth())
        {
            return true;
        }
        else if(firstDate.GetMonth() == secondDate.GetMonth())
        {
            if(firstDate.GetDay() > secondDate.GetDay())
            {
                return true;
            }
        }
    }
    return false;
}

    // Input stream operator overload
istream & operator >>( istream & input, Date & D) {

    D.SetDate(input);
    return input;

}
    // Output stream operator overload
ostream & operator <<( ostream & os, const Date & D) {

    D.GetDate(os);

    return os;

}
thedafferg
  • 99
  • 7
  • Can you please make a [mre]? A little example that we can just copy-paste into an ide and reproduce your problem without having to make any modifcations. Maybe it has something to do with the definition of `Date`. – Lukas-T Jun 08 '20 at 06:24
  • Hey, I put up an example as well as my Date.h and cpp for you to copy paste and try. The error produced in that example is that same that I am getting. Hope no difficulty using the example. Edit: Try with a float instead of a double in that example, that is a silly mistake i made – thedafferg Jun 08 '20 at 06:31
  • 2
    Well, thanks. That's something we can work with. In the future you should focus more on the minimal part - for example remove all the comments and unused functions, like io-operators. – Lukas-T Jun 08 '20 at 06:44
  • @john, multimap is a `std::map` variant that will allow you to have duplicate keys, unlike normal maps which only allow unique keys. I am trying to use a multimap because my data file has multiple float values of speed under the same date. – thedafferg Jun 08 '20 at 06:47
  • 3
    Now to some answers: I guess it would be a link-only answer, so basically two related questions here: `std::make_pair` is intended to automatically deduce the template parameters for you. It's not intended to be used with explicit parameters, see here: https://stackoverflow.com/a/9642232/5105949. Secondly, you need `operator<` for the map. You already have `operator>` so it should be easy to fix this one. Reference question: https://stackoverflow.com/a/1102720/5105949 – Lukas-T Jun 08 '20 at 06:47
  • @thedafferg yes, brain freeze, sorry about that. – john Jun 08 '20 at 06:48
  • 1
    Use of explicit template params in `make_pair(datetest, 47.5)` is the problem. Not sure of the explanation but just `make_pair(datetest, 47.5)` works fine. The point of `make_pair` is that you **don't** have to use explicit types. – john Jun 08 '20 at 06:49
  • 1
    You call to 'make_pair(Date&, float)' by providing a reference to Date. In my VisualStudio it shows that it expects a &&, so instead of make_pair(windlog[x].d, you should call something like make_pair(windlog[x].d.getACopy(), or make_pair(Date(windlog[x].d), – armagedescu Jun 08 '20 at 06:59
  • Thanks john and churill. When I removed the parameters for make_pair, and provided a < operator overload it seems to have worked! I can now create an iterator for the map and use it as I wish. – thedafferg Jun 08 '20 at 07:11

1 Answers1

0

Please check the following code and see if you can tweak it to get what you need. Basically I have created a Date class with date, month, year and speed members. The date is used as <operator to arrange the Date objects in order for the multiset. The multiset is created with the Date object as the key and speed member of that Date object as the value. Cheers! hope this helps.

class Date{
public:
    Date(int, int, unsigned int);
    int getDay()const {return day;};
    int getMonth()const {return month;};
    unsigned int getYear()const {return year;};
    void setSpeed(float s){ speed = s;};
    float getSpeed(){return speed;};

private:
    int day;
    int month;
    unsigned int year;
    float speed = 0;};

Date::Date(int d, int m, unsigned int y): day(d), month(m), year(y) {};

bool compareDay(const Date &a, const Date &b){
    return a.getDay() < b.getDay();
}

int main(){
    Date firstDate(23, 1, 1984);
    Date secondDate (12, 10, 2012);
    firstDate.setSpeed(20.3);
    secondDate.setSpeed(34.2);

    std::multimap<Date, float, decltype(compareDay)*> dateMap(compareDay);

    dateMap.insert({{firstDate, firstDate.getSpeed()}, {secondDate, secondDate.getSpeed()}});

for (auto i : dateMap){
    std::cout << (i.first).getDay() << "/" << (i.first).getMonth() << "/" << (i.first).getYear() << " - " << "Speed: " << (i.second) << std::endl;}
Hannu Hell
  • 11
  • 5