tags:

views:

176

answers:

7

Hi everyone! I want to implement a Swap() method for my class (let's call it A) to make copy-and-swap operator=(). As far as I know, swap method should be implemented by swapping all members of the class, for example:

class A 
{
  public:
    void swap(A& rhv) 
    {
        std::swap(x, rhv.x);
        std::swap(y, rhv.y);
        std::swap(z, rhv.z);
    }
  private:
    int x,y,z;
};

But what should I do if I have a const member? I can't call std::swap for it, so I can't code A::Swap().

EDIT: Actually my class is little bit more complicated. I want to Serialize and Deserialize it. Const member is a piece of data that won't change (its ID for example) within this object. So I was thinking of writing something like:

class A
{
  public:
    void Serialize(FILE* file) const
    {
        fwrite(&read_a, 1, sizeof(read_a), file);
    }

    void Deserialize(FILE* file) const
    {
        size_t read_a;
        fread(&read_a, 1, sizeof(read_a), file);
        A tmp(read_a);
        this->Swap(tmp);
    }

 private:
   const size_t a;
};

and call this code:

A a;
FILE* f = fopen(...);
a.Deserialize(f);

I'm sorry for such vague wording.

A: 

This is why const_cast was created. Just remember not to shoot your foot off.

Edit: OK, I concede - const_cast wasn't made for this problem at all. This might work with your compiler, but you can't count on it and if demons come flying out of your nostrils, please don't blame me.

Mark Ransom
This is definitely not the reason that `const_cast` was created. If the member is genuinely `const` then using `const_cast` to enable writing to that member will cause undefined behaviour. `const_cast` only enables writing to something that isn't `const` but where the writing code happens to only have a pointer to `const` or a `const` reference.
Charles Bailey
I don't think it's a good idea. As far as I know, const_cast on genuinely const object causes undefined behavior.
f0b0s
(+1) const_cast is used when the semantics of the language doesn't match the semantics of the problem at hand....
Hassan Syed
Eh, sorta. Put another way, const_cast is used when somebody screws up and you have to hack around it.
John Dibling
A: 

this is what mutable is for

note to self - read the question in detail otherwise you get downvoted :-(

pm100
Not really. `mutable` let's me change members in a `const` function, not change `const`'s in a mutating function.
GMan
The poster explicitly declared data members as `const`, so using `mutable` would defeat the point. (And it'd be simpler to remove the `const` qualifier anyway.)
jamesdlin
+5  A: 

I think what you really want is to have an internal data structure that you can easily exchange between objects. For example:

class A 
{
   private:

     struct A_Data {
       int x;
       int y;
       const int z;

       A_Data(int initial_z) : z(initial_z) {}
    };

    std::auto_ptr<A_Data> p_data;

  public:

     A(int initial_z) : p_data(new A_Data(initial_z)) {}

     void swap(A& rhv) {
        std::swap(p_data, rhv.p_data);
     }
};

This keeps the z value constant within any instance of A object internal data, but you can swap the internal data of two A objects (including the constant z value) without violating const-correctness.

Tyler McHenry
Magnificent code. :-) [I have no more votes for today :-(]
Notinlist
Yeah, except now A's copy constructor behavior is questionable at best and its assignment operator is flat-out broken. So don't forget to write a correct copy constructor and assignment operator if you go this route.
Jon-Eric
Well, yes, you still do have to follow the general rule of "if you need any of: Destructor, Copy Constructor, Assignment Operator, then you need all three." (and swap is a sort of assignment operator). The code above is intended to show the idea behind the const-correct swap, not be a complete implementation.
Tyler McHenry
+3  A: 

f0b0s, a good design principle is to design your objects to be immutable. This means that the object can't change once created. To "change" the object, you must copy the object and make sure to change the elements you want.

That being said, in this case you should look at using a copy constructor instead to copy the objects you want to swap, and then actually swap the references to the object. I can understand it'd be tempting just to be able to change the elements of an object under the hood, but it'd be better to make a copy of the object and replace the references to that object with the NEW object instead. This gets you around any const nastiness.

Hope this helps.

Polaris878
+1  A: 

I suggest you use pointers to the instances. The pointers can be swapped much easier than the data in the class or struct.

The only way to swap a constant value is to create another object, or clone the current object.

Given a struct:

struct My_Struct
{
  const unsigned int ID;
  std::string        name;
  My_Struct(unsigned int new_id)
    : ID(new_id)
  { ; }
};

My understanding is that you want to swap instances of something like My_Struct above. You can copy the mutable (non-const) members but not the const member. The only method to alter the const member is to create a new instance with a new value for the const member.

Perhaps you need to rethink your design.

Thomas Matthews
A: 

IMHO you must consider not to swap CONST members.

PD: I think you could consider to use reflection in your approach. so you don't have to maintain the function.

SDReyes
C++ does not support reflection.
Tyler McHenry
Thanks Tyler, I hadn't realized it. : )
SDReyes
+1  A: 

After a good nights sleep I think the best answer is to use a a non-const pointer to a const value -- after all these are the semantics you are trying to capture.

Hassan Syed
thank you, you are the only one, who understood the problem: I don't want to change VALUE, but change the ADDRESS (location) of const variable. I've done this using poiter it's the most elegant I think.
f0b0s