1. 4FIPS
  2. PHOTOS
  3. VIDEOS
  4. APPS
  5. CODE
  6. FORUMS
  7. ABOUT
/*
(c) 2012 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++
THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE
ARTICLE URL: http://forums.4fips.com/viewtopic.php?f=3&t=725
*/

#include <string>
#include <algorithm>
#include <cassert>
#include <iostream>

class Person
{
 public:

    Person(const std::string &first_name, const std::string &last_name, int age):
    _first_name(first_name), _last_name(last_name), _age(age)
    {
        // in general here might come quite a complex initialization, it would
        // be error prone to duplicate the logic in setters() and resetters()
        assert(!_first_name.empty() && !_last_name.empty());
        _initials = std::string(1, _first_name[0]) + std::string(1, _last_name[0]);
        assert(!std::any_of(_initials.begin(), _initials.end(), ::islower));
        _full_info = _first_name + " " + _last_name + ", aka " + _initials;
    }

    // just keep swap() in sync with the constructors and 'operator =', that's all!
    void swap(Person &other)
    {
        std::swap(_first_name, other._first_name);        
        std::swap(_last_name, other._last_name);
        std::swap(_age, other._age);
        std::swap(_initials, other._initials);
        std::swap(_full_info, other._full_info);
    }

    // just a bunch of getters, there's no need for setters() nor resetters() !!!
    const std::string & first_name() const { return _first_name; }
    const std::string & last_name() const { return _last_name; }
    int age() const { return _age; }

    // more getters...
    const std::string & full_info() { return _full_info; }

 private:

    std::string _first_name;
    std::string _last_name;
    int _age;

    // in general here come various derived or cached data...
    std::string _initials;
    std::string _full_info;
};

int main()
{
    Person p("Jonh", "Doe", 25);
    std::cout << p.full_info() << " (at " << &p << ")\n";

    // here comes the magic, set the last name by swapping the whole object
    Person(p.first_name(), "Foo", p.age()).swap(p);
    std::cout << p.full_info() << " (at " << &p << ")\n";

    // a full reset is also trivial, note that all the swaps() preserve
    // object's identity (address)
    Person("Jane", "Roe", 18).swap(p);
    std::cout << p.full_info() << " (at " << &p << ")\n";

    return 0;
}

// output:
// Jonh Doe, aka JD (at 002BF820)
// Jonh Foo, aka JF (at 002BF820)
// Jane Roe, aka JR (at 002BF820)