0

I have an ID-Record class and I want to block callers / users from using the operator== since it is ambiguous (user may want to compare only data field for equality).

Here's my class:

#include <string>
#include <functional>

class ID_Record
{
  public:
    bool operator==(const ID_Record& other) const
        {  throw std::bad_function_call(); }
    unsigned int id;  // Record ID used for database.
    std::string  value;
};

I would prefer to have operator==() "blocked" at compile time, so the compiler can catch it rather than at runtime.

The compiler should generate an error for this code:

ID_Record a(6, "Tree");
ID_Record b(3, "Platinum");
if (a == b) std::cout "Records are equal\n"; // This line should fail compilation.

I want to block cases of compiler generated functionality also.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154

1 Answers1

11

Since C++11, you can explicitly declare any class method/operator with = delete to prevent it from being callable, eg:

class ID_Record
{
  public:
    bool operator==(const ID_Record& other) const = delete;
    unsigned int id;  // Record ID used for database.
    std::string  value;
};

Online Demo

If code tries to invoke the deleted operator== in any way, the compile will fail with an error message, such as:

error: use of deleted function ‘bool ID_Record::operator==(const ID_Record&) const’

On the other hand, if you simply omit the operator== completely, eg:

class ID_Record
{
  public:
    unsigned int id;  // Record ID used for database.
    std::string  value;
};

Online Demo

Then you will also get a (different) compile error, such as:

error: no match for ‘operator==’ (operand types are ‘ID_Record’ and ‘ID_Record’)

The compiler will not generate a default operator== for you, unless you explicitly ask for it via = default in C++20 and later.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    This works! I'm getting the error message: `error C2280: 'bool MP_Records::Id_String::operator ==(const MP_Records::Id_String &) const': attempting to reference a deleted function` – Thomas Matthews Jul 22 '23 at 21:50
  • 1
    @ThomasMatthews This is analogous to doing (for example) `void Foo() = delete;` though. You wouldn't ever do that, so why explicitly delete `operator==`, which, as mentioned in the comments above, will not be generated by the compiler automatically (any more than `Foo` would) and is really just a regular old function with a funky name? So just don't declare it at all and you're golden (unless perhaps you prefer the compiler error Remy's answer generates when you try to use it). – Paul Sanders Jul 22 '23 at 23:56
  • I have updated my answer to include omitting the operator completely. – Remy Lebeau Jul 23 '23 at 02:11
  • For completeness, it would be worth mentioning that deleting `operator==` has a different effect from not declaring it. If you don't declare `operator==`, it's possible that some other `operator==` will get selected by overload resolution, if `ID_Record` is implicitly convertible to its argument types. – Brian Bi Jul 23 '23 at 20:32