How to prevent unused variable warning with non trivial destructor
Asked Answered
B

3

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?

Benzoate answered 13/11, 2017 at 6:2 Comment(7)
gcc does not warn for this case. This seems to be more of question about clang's warnings.Craunch
@Craunch Not just clang. Apparently msvc does this too. We discussed this in the comments but they were removed :(Benzoate
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.Ready
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?Lyceum
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?Myrick
@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.Vivienviviene
@Vivienviviene 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.Myrick
B
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};
Bensen answered 27/11, 2017 at 10:30 Comment(2)
This is a good answer but I think it’s not what OP is after (otherwise casting to void would also work).Charkha
@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..Bensen
D
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};
Dupre answered 27/11, 2017 at 10:25 Comment(0)
F
-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.

Faulk answered 27/11, 2017 at 10:11 Comment(1)
That will not extend the lifetime of the temporary thoughLyceum

© 2022 - 2024 — McMap. All rights reserved.