2

Using C++11.

I have a class I want to clean-up a bit by making the following changes:

From

class MyClass {
public:
  // code
private:
  MyClass(const MyClass&);
  MyClass& operator=(const MyClass&);
  // members
};

To

class MyClass {
public:
  // code
  MyClass(const MyClass&) = delete;
  MyClass& operator=(const MyClass&) = delete;
private:
  // members
};

Knowing that both are declared but not defined, will this change break binary compatibility? Does it improves anything?

cigien
  • 57,834
  • 11
  • 73
  • 112
A. Gille
  • 912
  • 6
  • 23
  • My experience is that changing object signatures always breaks binary compatibility. I would always assume you require a rebuild. I don't know what you're trying to improve, though. I presume you don't want either copy method used under any circumstances (even privately), so that probably does it. – Joseph Larson Dec 02 '20 at 15:50
  • The only nod to "binary compatibility" given by the Standard is the One Definition Rule, which describes sufficient conditions for separately compiled code to share a data type. That change does break the One Definition Rule. Linking together compilation units which disagree in this way is **undefined behavior**. – Ben Voigt Dec 02 '20 at 15:51
  • However, while the One Definition Rule describes sufficient conditions, in many actual implementations the necessary conditions are substantially weaker. Relying on any weaker conditions than the One Definition Rule will make your code non-portable. – Ben Voigt Dec 02 '20 at 15:53
  • My goal is to improve clarity and readability of source code leveraging C++11 features that adds expressiveness to my code, all that without breaking any kind of compatibility. While ones can expect a definition of a private copy constructor, marking it deleted is crystal clear about the intention of not being copyable. – A. Gille Dec 02 '20 at 15:56
  • @JosephLarson It's just an assumption, but I would expect that changing function signature causes binary incompatibility if the function is called somewhere. Here, in both cases, the functions may not be called anywhere in the generated assembly (it would cause undefined reference in the first case). – Daniel Langr Dec 02 '20 at 16:09

1 Answers1

2

If you switch from your first version to the second, where you have accessible, user-declared, deleted constructors, code like this will compile in C++11:

MyClass b{};

But if you upgrade to C++20, it won't. That might not be something you want. If you stick with your first version, where the constructors are inaccessible, the declaration of b won't compile in any language version, so you won't have this problem at least.

Here's a demo.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Migrating to C++20 has high chances to break binary compatibility anyway, so I guess this it not an issue – A. Gille Dec 02 '20 at 15:58
  • @A.Gille Fair enough. I'm just pointing out one potentially breaking change if you make the transition. There may very well be others, and some that affect you before you upgrade to C++20. – cigien Dec 02 '20 at 16:00
  • As the OP says that previously the functions were not `declared but not defined` then any errors will move from the link phase to the compile phase. Which may help in large projects. – Martin York Dec 02 '20 at 16:02
  • @A.Gille I've edited the question a bit. Is the edit ok? take it this doesn't really answer your question then? – cigien Dec 02 '20 at 16:13