3

I have a class named 'Card' and a class named 'CardDeck', with the following promotion defined in 'CardDeck.h':

CardDeck(Card card){cards.push_back(card);}

CardDeck has a friend operator+:

friend CardDeck operator+(const CardDeck, const CardDeck);

which works just fine for:

CardDeck+CardDeck
CardDeck+Card
Card+CardDeck

but it won't work for Card+Card. I get:

"no match for 'operator+' (operand types are 'Card' and 'Card')"

Why aren't the Cards being promoted to CardDecks in that case? I also tried overriding operator+ with:

friend CardDeck operator+(const Card, const Card);

but that doesn't work either. any hint why?

Thanks!

shayelk
  • 1,606
  • 1
  • 14
  • 32
  • 5
    Usually you pass `const CardDeck&`, i.e. const references to `operator +`. – PaulMcKenzie Jan 04 '16 at 21:06
  • I don't think it's the problem here. Could you show us last operator definition? – xinaiz Jan 04 '16 at 21:13
  • How is the compiler supposed to know you want a `CardDeck` from 2 `Deck`s? What if there are more classes that also expose constructors for `Card`? This would be ambigious. – Hatted Rooster Jan 04 '16 at 21:16
  • What would `friend CardDeck operator+(const Card, const Card)` do and on what object? Would you create a `CardDeck` object that added the 2 `Card`'s to it and returned that, i.e. `Card c1,c2; CardDeck cd = c1+c2`? – txtechhelp Jan 04 '16 at 21:19
  • 1
    This is a variation of the same theme: `std::string s = "a" + "b";` and expecting `+` to do a concatenation. – PaulMcKenzie Jan 04 '16 at 21:21
  • @PaulMcKenzie, no, it is not! There is no overload of operator+ for string literals defined. – SergeyA Jan 04 '16 at 21:23
  • 1
    The code is compilable (see answer by @BlackMoses). I believe, there is something else at play. – SergeyA Jan 04 '16 at 21:26
  • @SergeyA It isn't compilable here: http://ideone.com/UnuCEu – PaulMcKenzie Jan 04 '16 at 21:35
  • 1
    @SergeyA *no, it is not! There is no overload of operator+ for string literals defined* -- That's my point. There is no operator "+" for two string literals even though each can be implicitly converted to `std::string`, just like there there is no operator+ for two `Card` objects even though there is a conversion to a `CardDeck`. – PaulMcKenzie Jan 04 '16 at 21:41
  • @PaulMcKenzie Did you try to implement the function? – xinaiz Jan 04 '16 at 21:56
  • 1
    @PaulMcKenzie, this is because you never defined operator+. Here is the version which works: http://ideone.com/lkr5ME – SergeyA Jan 04 '16 at 21:59
  • @BlackMoses No, just trying to duplicate the OP's situation. . – PaulMcKenzie Jan 04 '16 at 22:00
  • Important detail: is `operator+` declared outside the class, or is its only declaration a definition with the `friend` keyword? – aschepler Jan 04 '16 at 22:34

3 Answers3

3

Works for me though!

class A
{
    public:
    A() {}
};

class B
{
public:
    B(A sth) {}
};

B operator+(const B x, const B y)
{
    return B(A());
}

using namespace std;

int main()
{
    A x;
    B y(x);
    y + y;
    x + y;
    y + x;
    x + x;
    return 0;
}

No errors expect unused parameters and expressions.

xinaiz
  • 7,744
  • 6
  • 34
  • 78
1

I'm thinking Black Moses has it partially right. It looks like you're declaring the implementation of the operator inside the class with the friend keyword. That creates the compilation error you're talking about, i.e. it appears you're doing the following:

class B
{
    public:
    B(A sth) { ... }

    friend int operator+(const B x, const B Y)
    {
        return 0;
    }

};

If you use what Black Moses did in his example, and add the following to your class:

friend int operator+(const B x, const B y);

then the compilation error goes away. To summarize: declare the operator a friend function inside your class definition, and then declare the implementation outside the class, like so:

int operator+(const B x, const B y)
{
    return 0;
}

Hope this helps.

xelius
  • 11
  • 2
  • operator+ is defined as a friend in the class, and is implemented in the source file, just as you suggest. still doesn't work... the weird thig is that I can't even get an overloaded version which takes two cards to work. – shayelk Jan 05 '16 at 20:14
0

turns out @PaulMcKenzie had the answer (unfortunatly I can't mark his comment as a solution): The operator was defined inside the class, so it wasn't available for 'Card'. For some reason I thought that implemanting it in the source file will be enough for it to be known by outsiders, but that's obviously not true as outsiders don't know anything about the source file. the code provided by Paul shows the solution:

http://ideone.com/lkr5ME

Thanks Paul!

a
shayelk
  • 1,606
  • 1
  • 14
  • 32