13

When I rely on lifetime extension to assign to a class with a non trivial destructor the compiler (both gcc and clang) issue unused variable warnings. Is there anyway to get around this? https://wandbox.org/permlink/qURr4oliu90xJpqr

#include <iostream>

using std::cout;
using std::endl;

class Something {
public:
    explicit Something(int a_in) : a{a_in} {}

    Something() = delete;
    Something(Something&&) = delete;
    Something(const Something&) = delete;
    Something& operator=(Something&&) = delete;
    Something& operator=(const Something&) = delete;

    ~Something() {
        cout << this->a << endl;
    }

private:
    int a;
};

int main() {
    const auto& something = Something{1};
    return 0;
}

Note that when I switch to not relying on lifetime extension, things work just fine https://wandbox.org/permlink/cJFwUDdi1YUEWllq

I even tried manually defining all the constructors and then deleting them with a templated static_assert so that it only fires when those constructors are called https://wandbox.org/permlink/fjHJRKG9YW6VGOFb

#include <iostream>

using std::cout;
using std::endl;

template <typename Type>
constexpr auto definitely_false = false;

template <typename T = void>
class Something {
public:
    explicit Something(int a_in) : a{a_in} {}

    Something() { static_assert(definitely_false<T>, ""); }
    Something(Something&&) { static_assert(definitely_false<T>, ""); }
    Something(const Something&) { static_assert(definitely_false<T>, ""); }
    Something& operator=(Something&&) { static_assert(definitely_false<T>, ""); }
    Something& operator=(const Something&) { static_assert(definitely_false<T>, ""); }

    ~Something() {
        cout << this->a << endl;
    }

private:
    int a;
};

int main() {
    const auto& something = Something<>{1};
    return 0;
}

Let's say just for the language lawyer tag's sake that casting to void is not an option. Can I do something with the constructors/destructors that will help silence this warning?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Curious
  • 20,870
  • 8
  • 61
  • 146
  • gcc does not warn for this case. This seems to be more of question about clang's warnings. – snow_abstraction Nov 17 '17 at 17:42
  • @snow_abstraction Not just clang. Apparently msvc does this too. We discussed this in the comments but they were removed :( – Curious Nov 17 '17 at 21:30
  • 1
    This is valid code so I think the language-lawyer tag is not appropriate, unless you are wanting confirmation that your code does not contain a bug. But your real question seems to be about hiding a bogus warning. The standard says nothing at all about the issuing of warnings for valid code. – M.M Nov 18 '17 at 02:07
  • Not a real answer, but would it be an option to create a local copy instead of the reference and rely on copy elision instead? – MikeMB Nov 27 '17 at 10:17
  • 1
    Why do you want to extend the lifetime in the first place? If you are not going to use that reference, how does your code access the object? – cmaster - reinstate monica Nov 27 '17 at 10:17
  • @cmaster-reinstatemonica a use case that I had: a class used for logging entries to and returns from a function (via OpenGL `glDebugMessageInsert` to easily orient in the `apitrace` output). Create an instance at the beginning of a function, and it'll automatically trace _any_ normal return—be it an early `return`, a `throw` from some nested function call, or reaching the end of the function. Though I didn't use a reference, just created an automatic object, but the unused variable warning is also a problem. – Ruslan Mar 31 '21 at 22:35
  • @Ruslan Ah, so it's only for deferring some action to the end of the scope. Well, I don't use exceptions, so I never had the problem of ensuring some action in case of one. I'd just write the respective action before the `return`. That said, I guess I would probably create a template class `Finally<>` or similar and pass its constructor a lambda (allows for catching local variables as well) if I had that problem. I would then search for some `__attribute__(())` voodo to squelch such warnings for that class. Or maybe some macro rites to add some "use" to the object. I don't know, it's tricky. – cmaster - reinstate monica Apr 01 '21 at 13:27

3 Answers3

8

Not the exact answer you are looking for, but here is a workaround suggestion:

Pre C++17

Use std::ignore like this:

const auto& something = Something{1};
std::ignore = something;

Post C++17

Use the maybe_unused attibute, like this:

[[maybe_unused]] const auto& something = Something{1};
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • This is a good answer but I think it’s not what OP is after (otherwise casting to `void` would also work). – Konrad Rudolph Nov 27 '17 at 10:38
  • @KonradRudolph I just witnessed the last part of the question (and edited to emphasize it a bit) and I agree with you..Should I delete it? I feel like a future user could be benefit from it, maybe.. – gsamaras Nov 27 '17 at 10:40
1

C++17 introduced the maybe_unused attribute, which may help in your case. It can be applied to a variable to indicate that it may be unused:

[[maybe_unused]] const auto & something = Something<>{1};
lisyarus
  • 15,025
  • 3
  • 43
  • 68
-2

I´d just use an anonymous Something object and your warning is gone...

int main() 
{
    Something{1};
    return 0;
}

https://wandbox.org/permlink/YcuLPFzgOSzltVSq

The compiler warns you that your Something's object reference variable is unused. That is true, for whatever you do with the constructor and destructor. So if you don't use the reference variable, don't create it. That effectively prevents the warning.

yussuf
  • 635
  • 1
  • 4
  • 18