1

MISRA rule 14-5-2 says:

A copy constructor shall be declared when there is a template constructor with a single parameter that is a generic parameter.

I can't find anything that explains to me in simple enough terms why there must be a copy constructor in such a case.

I've looked at Copy constructor of template class and C++ Template constructor, why is copy constructor being called?, but neither really helped me. I see mention that a copy constructor wouldn't exist, but doesn't the default one still get created? I saw references to copy elision, but I don't understand why the copy constructor is necessary for it.

As far as I can tell, this could fall under "good programming practice to watch out for"... or it could be "you've just entered into undefined behavior land". What should I look for to determine if the code that is violating this MISRA rule is causing a risk in its current code base?

Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76
  • 1
    Don't they put any reasoning (with examples) behind these rules? I can imagine that this particular rule is aimed at preventing situation when someone thinks that by passing `type const &` he is going to invoke this template constructor. C++ seem to have an ugly side regarding copy constructors. For example class can have deleted copy constructor but yet be properly `is_copy_constructible` – user7860670 Nov 01 '18 at 06:54
  • I wasn't able to find any reasoning. It's possible I just don't have enough resources. I'm using a static analysis tool that's quoting the rule and showing a failure, but doesn't give an explanation of the risks implied.or the reasoning for the rule. – Scott Mermelstein Nov 01 '18 at 11:03

1 Answers1

4

Unless you write a move constructor or move assignment operator, a copy constructor is always defined (possibly as deleted - or undefined prior to C++11). If you don't declare it yourself, it is auto-generated.

Now, I don't know enough about MISRA to be sure of the reasoning behind the rule you mention, so I'm going to guess what it is. If you have a template constructor with a single and generic parameter, then you might be doing more than a simple copy, and you may incorrectly think that all copy constructions will be done through this template constructor. But if you copy-construct an object of that class (the one with the template constructor) with another object of that same class or one derived from it, then the auto-generated copy constructor will be called, and none of the extra work that the template version is supposed to do will be done.

In short, by providing a copy constructor even when also providing a template constructor with a single and generic parameter, you make sure that copy constructions always work as intended. Moreover, you explicitly show the potential users of the class that it has a proper copy constructor in addition to the template constructor.

Scott Mermelstein
  • 15,174
  • 4
  • 48
  • 76
Nelfeal
  • 12,593
  • 1
  • 20
  • 39
  • @DanielLangr Before C++11, defining a move constructor would not undefine copy one for the former simply would not compile. 0_o – bipll Nov 01 '18 at 08:34
  • @DanielLangr I rephrased both parts. I was also going to say what bipll just said seconds ago: before C++11, copy constructors are *always* defined. – Nelfeal Nov 01 '18 at 08:35
  • MISRA-C++ is from 2008 and only applies to C++03. C++11 code cannot be MISRA-C++ compliant. – Lundin Nov 01 '18 at 08:38
  • @Nelfeal _"before C++11, copy constructors are always defined"_: again, this is incorrect. At least according to cppreference, copy constructor is always **declared**, but under some circumstances, it is **undefined** until C++11 (deleted since C++11). For instance, how could a compiler define copy constructor, if a non-static member variable has a private copy constructor? – Daniel Langr Nov 01 '18 at 10:19
  • @DanielLangr Oops, I got the two mixed up: the copy constructor is indeed always declared, although not defined if implicitly-declared and a move constructor or move assignment operator is declared, or, prior to C++11, if it would be deleted in C++11. – Nelfeal Nov 01 '18 at 10:31
  • 1
    @Lundin I think that's a key point there. The code is written in C++11, and the MISRA 2008 standards are being applied against it. Is it likely then that this violation is more an artifact of applying an older standard against the code than of some actual unsafe coding practice? – Scott Mermelstein Nov 01 '18 at 10:56
  • @ScottMermelstein Not just that: C++11 should not be used in safety-critical applications. The `auto` keyword alone is a rampant safety hazard. Until someone makes a MISRA-C++1x (or similar safe subset) that bans the use dangerous C++1x features, C++ should be outlawed for use in such applications. – Lundin Nov 01 '18 at 11:57
  • 1
    @Nelfeal I finally found the MISRA standard, and they give an explanation for their rule. Yours is dead-on. I took the liberty of bolding the part of your answer that resonated perfectly. The rest of your answer is still great content, but I wanted to highlight this bit. You're obviously welcome to undo my changes. – Scott Mermelstein Nov 28 '18 at 17:09