Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this an incorrect warning?

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.

like image 993
xryl669 Avatar asked Dec 31 '22 05:12

xryl669


2 Answers

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.

like image 180
eerorika Avatar answered Jan 05 '23 15:01

eerorika


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.

like image 26
Asteroids With Wings Avatar answered Jan 05 '23 14:01

Asteroids With Wings