0

I have a code:

#include "stdafx.h"
#include "memory"
#include <gtest\gtest.h>
class Money
{
public:
    explicit Money(int value) :value(value) {} ;
    Money(Money&& m) :value(m.returnValue()) {};
    Money(const Money &m) = default;
    Money operator-(const Money &m) ;
    Money &operator=(Money &&m) { return Money(m.returnValue()); };
    Money &operator=(const Money &m)=default;
    int returnValue() const { return value; };
    ~Money() = default;
private:
    int value;
};
Money Money::operator-(const Money &m)
{
    return Money(value - m.returnValue());
}


class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
    int returnMoney() const { return propertiesBank->money->returnValue(); }
    ~Bank() = default;
private:
    struct PropertiesBank;
    std::unique_ptr<PropertiesBank> propertiesBank;
};

struct Bank::PropertiesBank
{
    std::shared_ptr<Money> money;
    PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};
int main()
{
    Money k(1000);
    Bank bank(k);
    return 0;
}

I want display(returnMoney()) money in the Bank, but I can't. I could make class with struct Impl and unique_ptr for training. I know, that unique can't copy. How can I make this programm? Are the rest of my code is well?

Error

Error C2027 use of undefined type 'Bank::PropertiesBank' Error
C2039 'returnValue': is not a member of 'std::unique_ptr>'

21koizyd
  • 1,515
  • 9
  • 24
  • 2
    When you say that you "can't", what do you mean by that? Do you get build errors? Run-time errors or crashes? Unexpected results? Please elaborate! And also please [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask). – Some programmer dude Jan 05 '17 at 00:23
  • 1
    Since you want to define `PropertiesBank` out of class, you need to define the function that uses it out of class, too: its implementation has to be after the struct definition. With that change, [your code compiles](http://rextester.com/UVFJ63318) – Igor Tandetnik Jan 05 '17 at 00:25
  • 1
    Ah, build errors. Then edit your question to include the *full* and *complete* and *unedited* output of the compiler. Simply copy-paste the output when you build into the question body, as text. – Some programmer dude Jan 05 '17 at 00:29

2 Answers2

2

The only issue I can see is that the definition of Bank::returnMoney tries to access Bank::PropertiesBank when it has only been forward-declared, not defined. Moving PropertiesBank to be defined incline within Bank fixes this.

However as Mooing Duck points out in the comments, if your intention is to implement the pImpl idiom, then both Bank::PropertiesBank and Bank::returnMoney should be defined in a .cpp file, rather than within the class definition.

#include <memory>

class Money
{
public:
    explicit Money(int value) :value(value) {} ;
    Money(Money&& m) :value(m.returnValue()) {};
    Money(const Money &m) = default;
    Money operator-(const Money &m) ;
    Money operator==(Money &&m) { return Money(m.returnValue()); };
    int returnValue() const { return value; };
    ~Money() = default;
private:
    int value;
};

Money Money::operator-(const Money &m)
{
    return Money(value - m.returnValue());
}

class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
    int returnMoney() const { return propertiesBank->money->returnValue(); }
    ~Bank() = default;
private:
    struct PropertiesBank
    {
        std::shared_ptr<Money> money;
        int returnMoney() const { return money->returnValue(); }
        PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
    };

    std::unique_ptr<PropertiesBank> propertiesBank;
};

#include <iostream>

int main()
{
    Money m(10);
    Bank b(m);

    std::cout << b.returnMoney();
    return 0;
}
Community
  • 1
  • 1
David Scarlett
  • 2,831
  • 2
  • 8
  • 26
1

Its not a problem with std::unique_ptr, its the fact that you tried accessing a member of an object whose type is PropertiesBank when the compiler hasn't seen its full definition. You should move the definition of the member function outside the class and at the point where the compiler has seen the full definition of PropertiesBank:

See the comment in this snippet below:

class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};

    int returnMoney() const;{ return propertiesBank->money->returnValue(); }
    // .......The compiler doesn't know that `money`^^^^^^ belongs to `PropertiesBank`

    ~Bank() = default;
private:
    struct PropertiesBank;
    std::unique_ptr<PropertiesBank> propertiesBank;
};

struct Bank::PropertiesBank
{
    std::shared_ptr<Money> money;
    PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};

You should move the function's definition to after where the compiler has seen the definition of the type of propertiesBank:

class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
    int returnMoney() const;    //member function declaration
    ~Bank() = default;
private:
    struct PropertiesBank;
    std::unique_ptr<PropertiesBank> propertiesBank;
};

struct Bank::PropertiesBank
{
    std::shared_ptr<Money> money;
    PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};

//Member function's definition
int Bank::returnMoney() const { return propertiesBank->money->returnValue(); }
WhiZTiM
  • 19,970
  • 3
  • 36
  • 56
  • But variable "k" have value the same after construct Bank. What's wrong in my solution? I think, that if I move Money to the Bank, that Money haven't value. I'm right? – 21koizyd Jan 05 '17 at 01:06
  • 1
    @21koizyd ...When you `std::move` from an object, ***A*** and another object or function, ***B*** grabs it via an *rvalue* reference. The state of ***A*** entirely depends whatsoever ***B*** decides to do with it. So the state of `Money` after moving from it depends on what you did with the move constructor. And by the way... In the `int main()` of your original code, you did not `std::move` *k* into *bank*.... Also see [this](http://stackoverflow.com/questions/14679605/do-built-in-types-have-move-semantics) (notably the last sentence n the Accepted answer) – WhiZTiM Jan 05 '17 at 01:25
  • Okey, I was thinking about this possibility :). So, thanks :) – 21koizyd Jan 05 '17 at 02:00