0

I was reading about the copy swap idiom and in an example the swap method was implemented in the following way:

class Derived : public Base
{
      public:
      std::string title = "";
      details *detail = nullptr;

      void swap(Derived& lhs, Derived& rhs) 
      {
         using std::swap;
         Base& lb = static_cast<Base&>(lhs); 
         Base& rb = static_cast<Base&>(rhs);
         std::swap(lb,rb);
         std::swap(lhs.title, rhs.title);
         std::swap(lhs.detail, rhs.detail);
      }

      //Regular Contructor
      Derived() { /*...*/ }
      ....
}

Now in the swap method is there a special reason that static_cast was used. Will it be safe to use a dynamic cast like this

Base* lb = dynamic_cast<Base*>(&lhs)
Base* rb = dynamic_cast<Base*>(&rhs)
std::swap(*lb,*rb);
MistyD
  • 16,373
  • 40
  • 138
  • 240
  • First, I think your code is wrong, you should replace `base` by `Base &`. Then if you want to use a dynamic_cast, you should write `std::swap(*lb,*rb)` else it doesn't swap the base members. And finally always prefer static_cast over dynamic_cast, because it's done at compile time (dynamic_cast could fail at run-time). – Olivier Sohn Jul 29 '18 at 08:08
  • What does the copy-then-swap idion have to do with your code? – StoryTeller - Unslander Monica Jul 29 '18 at 08:15
  • @OlivierSohn i fixed the typo – MistyD Jul 29 '18 at 08:16
  • @MistyD what is `base` ? – Olivier Sohn Jul 29 '18 at 08:17
  • @OlivierSohn sorry I meant `Base` – MistyD Jul 29 '18 at 08:19
  • Ok, now you should probably replace `Base` by `Base&` in the swap method, else I think it doesn't work, because you will swap copies of the objects instead of the objects themselves. – Olivier Sohn Jul 29 '18 at 08:22
  • I agree. Thanks – MistyD Jul 29 '18 at 08:23
  • @OlivierSohn - You are answering in comments. – StoryTeller - Unslander Monica Jul 29 '18 at 08:23
  • @StoryTeller Well I'm trying to clarify what the question is, the code didn't make sense so now it does :) – Olivier Sohn Jul 29 '18 at 08:26
  • @OlivierSohn - There was nothing lacking in clarity. And your first comment is an answer, plain and simple. The suggestion to prefer static cast goes directly to the heart of the question. Nothing in your suggestion improved the question, it fixed the issues in the OP's code. Those fixes belong in an answer. Where they can be properly voted upon. Especially when you say something unfounded, like `dynamic_cast` happening at runtime here. – StoryTeller - Unslander Monica Jul 29 '18 at 08:30
  • @StoryTeller dynamic_cast always happen at runtime, don't they? – Olivier Sohn Jul 29 '18 at 08:31
  • @OlivierSohn - No. Not always, as the correct accepted answer explains. Only down-casts and side-casts happen at runtime. Up-casts always resolve statically. Otherwise it would be poor design for a language that professes to give you zero-overhead as often as possible. – StoryTeller - Unslander Monica Jul 29 '18 at 08:33
  • @StoryTeller I think you're wrong. Please read https://stackoverflow.com/questions/2253168/dynamic-cast-and-static-cast-in-c. It happens at runtime. So yes you should prefer static_cast over dynamic_cast in that case. – Olivier Sohn Jul 29 '18 at 08:38
  • @OlivierSohn - OMG, a wrong fact in an answer that is highly voted upon due to popularity! How so very unlike SO.... But seriously. I don't need to read that answer further. I read the C++ standard. [I suggest you do the same](https://timsong-cpp.github.io/cppwp/n4659/expr.dynamic.cast#5). A type doesn't need to be polymprhic for the purpose of up casts (note the "otherwise" in p4). How can non-polymprhic types be up cast then? Statically of course. – StoryTeller - Unslander Monica Jul 29 '18 at 08:42
  • @StoryTeller ok, I was convinced of the opposite, so I learned something today! – Olivier Sohn Jul 29 '18 at 09:24

1 Answers1

2

You can always static_cast to an unambiguous visible base class. dynamic_cast is used in the opposite direction - casting from a base class pointer/reference to potentially invalid derived class. It is completely unnecessary here, but yes, it is safe, because it will have the same effect as static_cast.

Look at the 3rd point here.

3) If new_type is a pointer or reference to Base, and the type of expression is a pointer or reference to Derived, where Base is a unique, accessible base class of Derived, the result is a pointer or reference to the Base class subobject within the Derived object pointed or identified by expression. (Note: an implicit cast and static_cast can perform this conversion as well.)

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
  • Thanks for clearing that up. On a side note I have also seen static_cast cast downwards (base to derived) where a dynamic cast would be better since it gives checking. I still get confused most of the times on exactly when to use static_cast so I just stick with dynamic cast – MistyD Jul 29 '18 at 08:26
  • I disagree : it doesn't have the same effect, as dynamic_cast is done at runtime. the result is the same as static_cast, but the overhead is bigger when using dynamic_cast. – Olivier Sohn Jul 29 '18 at 08:39
  • @MistyD There are cases when you don't want a run-time check, because you *know* that the `static_cast` will succeed. It's like checking vector's size once and then using `operator[]` instead of `at`. – LogicStuff Jul 29 '18 at 09:08
  • @OlivierSohn The run-time check happens only when you're truly using `dynamic_cast` above the capabilities of `static_cast`. What you claim does not make much sense to me. – LogicStuff Jul 29 '18 at 09:15
  • 1
    @LogicStuff indeed, I thought that the rtti type check was done in all cases, but it seems it's not. Thanks for pointing that out! – Olivier Sohn Jul 29 '18 at 09:25