0

I am trying to make an aggregate class, Pile, that takes a vector of Cards as its data.

I have been trying to figure out what the deal is with this error for the past 3 hours and am stumped. Here is the error:

In file included from /usr/include/c++/5/vector:62:0,
                 from Pile.h:16,
                 from Pile.cpp:15:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Card; _Args = {}]’:
/usr/include/c++/5/bits/stl_uninitialized.h:519:18:   required from ‘static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Card*; _Size = long unsigned int; bool _TrivialValueType = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:575:20:   required from ‘_ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Card*; _Size = long unsigned int]’
/usr/include/c++/5/bits/stl_uninitialized.h:637:44:   required from ‘_ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, std::allocator<_Tp>&) [with _ForwardIterator = Card*; _Size = long unsigned int; _Tp = Card]’
/usr/include/c++/5/bits/stl_vector.h:1311:36:   required from ‘void std::vector<_Tp, _Alloc>::_M_default_initialize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = Card; _Alloc = std::allocator<Card>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/5/bits/stl_vector.h:279:30:   required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = Card; _Alloc = std::allocator<Card>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<Card>]’
<span class="error_line" onclick="ide.gotoLine('Pile.cpp',27)">Pile.cpp:27:23</span>:   required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: no matching function for call to ‘Card::Card()’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^
In file included from Pile.h:17:0,
                 from Pile.cpp:15:
card.h:30:5: note: candidate: Card::Card(const Card&)
     Card(const Card& old);     //copy constructor
     ^
card.h:30:5: note:   candidate expects 1 argument, 0 provided
card.h:29:5: note: candidate: Card::Card(int, char)
     Card(int r, char s); //parameterized constructor
     ^
card.h:29:5: note:   candidate expects 2 arguments, 0 provided

Call Stack
#   Function    File:Line
Local Variables
Variable    Value
Display Expressions
Expression  Value   
Breakpoints and Watchpoints
    #   Description 

I feel like I am so close I had a bunch of other errors I was able to solve but I can't get passed this "In file included from" error as I can't make out what it even means. I have tested my card class alone and it is functioning as intended.

Here is my Pile.h code:

#ifndef PILE_H
#define PILE_H
#include <vector>
#include "card.h"

using namespace std;

class Pile 
{
protected:
    vector<Card> p;

public:

    Pile();
    Pile(vector<Card> p);

    Card dealCard();
    int getCount();
    void shuffle();
    void clear();
    Pile operator + (const Card& c) const;
    Pile operator + (Pile& b);
    friend ostream& operator << (ostream& out, const Pile& p);

};

and here is my Pile.cpp code:

#include "Pile.h"
#include <iomanip>
#include <algorithm>  //shuffle
#include <time.h>
#include <sstream>
#include <stdexcept>
#include <cstdlib>

using namespace std;

Pile::Pile()
{
    p = vector<Card>(0);
}

Pile::Pile(vector<Card> p)
{
    this->p = p;
}

//draws card from the top of the pile and removes it from the vector
Card Pile:: dealCard()
{
    if(p.size() > 0)
    {
        Card tempCard = p.front();
        p.erase(p.begin());

        return tempCard;
    }
    else
        throw std::length_error("Pile is empty");


}

int Pile:: getCount()
{
    return p.size();
}

void Pile:: shuffle()
{
    srand(unsigned(time(NULL)));
    random_shuffle(p.begin(), p.end());
}

void Pile:: clear()
{
    p.clear();
}

Pile Pile:: operator + (const Card& c) const
{
    Pile tempPile(p);       //make a copy of the pile to be returned
    tempPile.p.push_back(c);  //push the new card onto the end of the pile
    return tempPile;        //return the new pile
}

Pile Pile:: operator + (Pile& b)
{
    Pile tempPile(p);

    while(b.p.size() > 0)
    {
        tempPile.p.push_back(b.p.front());
        b.p.erase(b.p.begin());
    }
    return tempPile;
}

ostream& operator << (ostream& out, const Pile& p)
{
    int count = 0;
    int index = 0;

    while(p.p.size() > 0)
    {
        out << p.p[index] << setw(2);
        count++;
        index++;

        if(count == 10)
        {
            out << endl;
            count = 0;
        }
    }
}

My best guess is that maybe I am missing a #include somewhere. I tried googling the issue for the past couple hours and the only thing I can come up with is to move "using namespace std" but I have tried that and I am still getting the error.

Edit:

Here is my Card.cpp

#include <cstdlib>
#include "card.h"
#include <sstream>
#include <stdexcept>
using namespace std;

Card::Card(int r, char s)
{
    if(r <= 13 && r > 0)
        this->r = r;
    else
        throw std::invalid_argument("Rank must be valid (1-13)");

    if(s == 'd' || s == 'D')        //diamonds
        this->s = 'D';
    else if(s == 'h' || s == 'H')   //hearts
        this->s = 'H';
    else if(s == 's' || s == 'S')   //spades
        this->s = 'S';
    else if(s == 'c' || s == 'C')   //clubs
        this->s == 'C';
    else
        throw std::invalid_argument("Suit must be valid (H, S, C, D");
}

Card::Card(const Card& old)
{
    r = old.r;
    s = old.s;
}

void Card::setCard(int r, char s)
{
    if(r <= 13 && r > 0)
        this->r = r;
    else
        throw std::invalid_argument("Rank must be valid (1-13)");

    if(s == 'd' || s == 'D')        //diamonds
        this->s = 'D';
    else if(s == 'h' || s == 'H')   //hearts
        this->s = 'H';
    else if(s == 's' || s == 'S')   //spades
        this->s = 'S';
    else if(s == 'c' || s == 'C')   //clubs
        this->s == 'C';
    else
        throw std::invalid_argument("Suit must be valid (H, S, C, D");
}

int Card::getRank()
{
    return r;
}

 bool Card:: operator == (const Card c) const
 {
     if(r == c.r)
         return true;
     else
         return false;
 }

 bool Card:: operator >(const Card c) const
 {
     if(r > c.r)
         return true;
     else
         return false;
 }

 ostream& operator << (ostream& out, const Card c)
 {
     if(c.r == 1)
         out << "A" << c.s;
     else if(c.r > 1 && c.r <= 10)
         out << c.r << c.s;
     else if(c.r == 11)
         out << "J" << c.s;
     else if(c.r == 12)
         out << "Q" << c.s;
     else      //must be king
         out << "K" << c.s;
 }

and card.h:

#ifndef CARD_H
#define CARD_H

#include <string>
#include <iostream>
using namespace std;

class Card
{
private:
    int r;      
    char s;

public:

    Card(int r, char s); //parameterized constructor
    Card(const Card& old);     //copy constructor

    void setCard(int r, char s);
    int getRank();
    bool operator ==(const Card c) const;
    bool operator >(const Card c) const;
    friend ostream& operator << (ostream& out, const Card c);

};
Sauromayne
  • 105
  • 10
  • *no matching function for call to ‘Card::Card()’* Looks like Card needs a default constructor. – user4581301 Nov 30 '18 at 03:43
  • [Get rid of the `using namespace std;` in the header file](https://stackoverflow.com/questions/4872373/why-is-including-using-namespace-into-a-header-file-a-bad-idea-in-c). Post the `Card` class. – PaulMcKenzie Nov 30 '18 at 03:43
  • `srand` should usually only be called once per program ad this looks to fall into usually. Remove it from `Pile:: shuffle()` and put it somewhere near the top of the `main` function. – user4581301 Nov 30 '18 at 03:46
  • @PaulMcKenzie I removed using namespace std; and posted the card class. – Sauromayne Nov 30 '18 at 03:57
  • @user4581301 Thank you I removed it from the class file and added to main. I added a default constructor and it worked. Do you need a default constructor no matter what? I'm not using default constructor for anything so why does it need it? – Sauromayne Nov 30 '18 at 03:57
  • 1
    There is no need for `Card` to have a user-defined copy constructor or assignment operator. Also, you may not be needing the default constructor, but what if `vector` needs it? Aha. – PaulMcKenzie Nov 30 '18 at 04:01
  • 1
    The real error message starts `error: no matching function for call to ‘Card::Card()’` , the stuff before it is explaining where we were at in the compliation process before this problem occurred – M.M Nov 30 '18 at 04:36

2 Answers2

3

The issue is this line:

p = vector<Card>(0);

Initializing vectors this way requires a default constructor. Please see std::vector constructor (3). You can simply remove that line, since it really isn't necessary. A std::vector starts out as empty anyway, so there is no need to do redundant work.

You will see that if you remove that line, you will note that your code will compile without need of a default constructor. However if you add more code, you need to be careful you're not using std::vector in a way where the default constructor is needed. Thus it may not hurt just to provide a default constructor.


Having said that, your code produced a few warnings that you need to address. For example, in your overloaded << operators, you failed to return a value. Returning nothing from a function that is supposed to return a value leads to undefined behavior.

The other issue is that there is no need for you to write a user-defined copy constructor for either Pile or Card, since both classes have all their members containing correct copy semantics (int, char, for the Card class, and std::vector<Card> for the Pile class). There is no need to introduce code that the compiler provides to you for free, without bugs, and is efficient.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
0

Default constructor for Card class is missing. C++ does not generate default constructor when user defined constructor (with parameters or without parameters) is present in the class. In your code default constructor is need in Pile.cpp:27.

rakesh.sahu
  • 465
  • 8
  • 18