11

I have a custom class implementing operator== with nullptr.

Here is my code dumbed down into a simple example:

#include <cstdint>
#include <iostream>

class C {
private:
    void *v = nullptr;

public:
    explicit C(void *ptr) : v(ptr) { }

    bool operator==(std::nullptr_t n) const {
        return this->v == n;
    }
};

int main()
{
    uint32_t x = 0;
    C c(&x);
    std::cout << (c == nullptr ? "yes" : "no") << std::endl;

    C c2(nullptr);
    std::cout << (c2 == nullptr ? "yes" : "no") << std::endl;


    return 0;
}

The code works as expected but g++ (version 6.2.1) gives me the following warning:

[Timur@Timur-Zenbook misc]$ g++ aaa.cpp -o aaa -Wall -Wextra
aaa.cpp: In member function ‘bool C::operator==(std::nullptr_t) const’:
aaa.cpp:12:36: warning: parameter ‘n’ set but not used [-Wunused-but-set-parameter]
     bool operator==(std::nullptr_t n) const {
                                    ^

What am I doing wrong?

NOTE: I'm using -Wall -Wextra.

rocambille
  • 15,398
  • 12
  • 50
  • 68
Venemo
  • 18,515
  • 13
  • 84
  • 125
  • Cannot reproduce. No warnings with gcc 6.2.1 – Sam Varshavchik Nov 24 '16 at 15:40
  • 3
    @SamVarshavchik try -Wall -Wextra. Reproducible on wandbox's 6.1: http://melpon.org/wandbox/permlink/OGeniUkFzE8dRP1v – krzaq Nov 24 '16 at 15:41
  • 1
    Interesting. Note that you can dumb it down even further: `#include int main() { std::nullptr_t n = nullptr; if (n == nullptr) std::cout << "yes"; }` – Christian Hackl Nov 24 '16 at 15:53
  • 1
    @wasthishelpful: Perhaps GCC turns out to be correct in generating a warning here, but the wording *"parameter set but not used"* certainly leaves much to be desired. – Christian Hackl Nov 24 '16 at 15:59
  • 1
    Adding `n=n;` to the function makes the warning go away. Looks like the compiler knows that `n` can be `NULL`, and simply optimizes the reference to it away, then ends up producing a warning. – Sam Varshavchik Nov 24 '16 at 16:02
  • 2
    lvalue-to-rvalue conversion on a `nullptr_t` object doesn't access its stored value. Should probably file a bug anyway. – T.C. Nov 24 '16 at 19:12
  • @ChristianHackl Are you suggesting that this is in fact a bug in `g++`? – Venemo Nov 30 '16 at 11:58
  • @Venemo: Maybe, if it's supposed to be a different warning or none at all. Or it's a not-yet-supported feature. Or nobody has defined the expected/desired behaviour yet. It's neither right nor wrong because the standard does not mandate a diagnostic message, so whatever a compiler does here is a quality-of-implementation issue. – Christian Hackl Nov 30 '16 at 17:03

1 Answers1

9

Not really an answer on why this happens, but anyway what value could have n but nullptr?

Returning this->v == nullptr and making the argument unnamed removes the warning:

bool operator==(std::nullptr_t) const {
    return this->v == nullptr;
}

EDIT:

Declaring n as an rvalue reference, or as a const lvalue reference also removes the warning:

bool operator==(std::nullptr_t&& n) const {
    return this->v == n;
}

bool operator==(const std::nullptr_t& n) const {
    return this->v == n;
}

EDIT2:

More ways to silence a warning about unused variables can be found in this question (thx @ShafikYaghmour for pointing it in the comments). The examples above cover the "implicit" ways.

Explicit solutions are available, but IMHO look less coherent since the parameter is effectively used. Tested explicit solutions include:

bool operator==(std::nullptr_t n) const {
    (void)n;
    return this->v == n;
}

#define UNUSED(expr) do { (void)(expr); } while (0)

bool operator==(std::nullptr_t n) const {
    UNUSED(n);
    return this->v == n;
}

Non portable solution for GCC:

bool operator==(__attribute__((unused)) std::nullptr_t n) const {
    return this->v == n;
}
Community
  • 1
  • 1
rocambille
  • 15,398
  • 12
  • 50
  • 68