这是一个错误的警告吗?

Is this an incorrect warning?

让我们看看这个我经常看到的代码模式:

struct Foo
{
    template <typename T>
    T* as1() { /* ... */ }

    template <typename T>
    T* as2(T*) { /* ... */ }  
};   

前一种方法是这样使用的:

    SomeComplexTypeAndNotAuto * a = foo.as1<SomeComplexTypeAndNotAuto>();

虽然后者使用起来更方便,因为您不需要重复复杂类型:

    SomeComplexTypeAndNotAuto * a = foo.as2(a); 

但是,大多数编译器会拒绝第二种情况并发出 Wuninitialized 警告:

warning: variable 'a' is uninitialized when used within its own initialization [-Wuninitialized]

很明显变量没有用在初始化中,只有它的类型。有没有办法在不处理每个编译器 pragma 的情况下避免此警告?

编辑:

从我最初的 post 看不清楚,但是当我写 SomeComplexTypeNotAuto 时,我的意思是这样的代码: auto a = foo.as2(a); 无法解析,因为您 必须 提供一种类型以允许编译器推断它。

我的问题具体到方法 as2() 是一个模板这一事实,因此在类型 T 的特化时必须可见。所以编译器可以看到参数 T* 甚至没有名称,所以它不是来自函数内部的 used/usable。因此,我不明白为什么它会警告 "unused variable" 警告,因为很明显它没有被使用。

It's quite clear the variable is not used in the initialization

相反,很明显变量用于函数参数的初始化。程序的行为未定义。

Is this an incorrect warning?

不,警告是正确的。


一个简单的解决方法是将参数更改为引用:

T* as2(T*&)

请特别注意不要实际读取引用的值。

从 C+11 开始,您可以使用 auto 代替。

不清楚该变量是否未用于初始化。 as2.

里面可能发生任何事情

如果未使用该变量,则不要传递它 - 而是使用显式模板实例化。

警告是正确的。

a 在它自己的初始化器中有一个未指定的值,并且将它作为函数参数按值传递需要复制它,这需要从它读取,它具有未定义的行为。

不使用结果值并不重要。


您可以通过阻止复制(使用引用参数)来 "fix" 它,但您最终会得到非常奇怪和不寻常的代码,让您的读者感到困惑。我真的不建议使用这种方法。

只需拼出类型,最好先使其更短且更易读。

按照惯例,我们像这样跳过重复的类型名称:

auto* a = foo.as1<SomeComplexTypeAndNotAuto>();

(例如使用 std::make_shared 和朋友时)

另外,查看访问者模式。