How to prevent unused variable warning with non trivial destructor

How to prevent unused variable warning with non trivial destructor

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 

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 

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

template 
constexpr auto definitely_false = false;

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

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

    ~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?

Solutions/Answers:

Answer 1:

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};

Answer 2:

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};

Answer 3:

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.

Our Awesome Free Tools

References

Can I use the result of a C++17 captureless lambda constexpr conversion operator as a function pointer template non-type argument?

Can I use the result of a C++17 captureless lambda constexpr conversion operator as a function pointer template non-type argument?

While answering How do I write a lambda expression that looks like a method?, I tried to turn a captureless lambda into a member function pointer by exploiting the fact that, since C++17, captureless lambdas have a constexpr conversion operator to their function pointer type.
So I came up with an issue boiling down to:
template struct A{};

int main()
{
  A([]{})>{}; // 1

  constexpr auto fp = static_cast([]{});
  A{}; // 2
}

Now, this compiles in clang (since 5.0.0) but gcc(>=7.2) complains: 
error: lambda-expression in template-argument
   A([]{ /*whatever*/ })>{}; // 1
                            ^
error: 'main()::::_FUN' is not a valid template argument for type 'void (*)()' because 'static constexpr void main()::::_FUN()' has no linkage
   A{}; // 2

The question is, who's right?

Solutions/Answers:

Answer 1:

This is a gcc bug, filed 83258.

In C++14, we used to have a linkage requirement for non-type template parameters of pointer type. But in C++17 (as a result of N4268), the parameter just needs to be a converted constant expression of the correct type, with a few other restrictions (none of which are relevant here). Once we can construct fp, we should be able to use it as a template parameter.

Our Awesome Free Tools

References