Let's see this code pattern I'm seeing often:
struct Foo
{
template <typename T>
T* as1() { /* ... */ }
template <typename T>
T* as2(T*) { /* ... */ }
};
The former method is to be used like this:
SomeComplexTypeAndNotAuto * a = foo.as1<SomeComplexTypeAndNotAuto>();
While the latter is more convenient to use since you don't need to repeat the complex type:
SomeComplexTypeAndNotAuto * a = foo.as2(a);
However, most compiler rejects the 2nd case with a Wuninitialized warning:
warning: variable 'a' is uninitialized when used within its own initialization [-Wuninitialized]
It's quite clear the variable is not used in the initialization, only its type is. Is there a way to avoid this warning without dealing with the hell of per-compiler pragma ?
Edit:
It's not clear from my initial post, but when I wrote SomeComplexTypeNotAuto
, I meant that such code like this:
auto a = foo.as2(a);
can not be resolved since you have to provide one type to allow the compiler to deduce it.
My question was specific to the fact that method as2()
is a template, as as such must be visible at specialization time for a type T
. So the compiler can see that the argument T*
does not even have a name so it's not used/usable from within the function. As such, I don't get why it warns about the "unused variable" warning since it's clear it's not used.
It's quite clear the variable is not used in the initialization
On the contrary, it is quite clear that the variable is used in the initialisation of the function argument. The behaviour of the program is undefined.
Is this an incorrect warning?
No, the warning is correct.
A simple fix is to change the argument into a reference:
T* as2(T*&)
Just be extra sure to not actually read the referred value.
Since C+11, you can use auto
instead however.
The warning is correct.
a
has an unspecified value in its own initialiser, and passing it as a function argument by value requires it to be copied, which requires reading from it, which has undefined behaviour.
It does not matter that you do not then use what would have been the resulting value.
You can "fix" it by preventing the copy (with a by-reference argument) but you're going to end up with very strange and unusual code that confuses your readers. I really do not advise this approach.
Just spell out the type, ideally making it shorter and more readable first.
Conventionally, we skip the repeated type name like this:
auto* a = foo.as1<SomeComplexTypeAndNotAuto>();
(e.g. when using std::make_shared
and friends)
Also, look up the visitor pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With