让我们看看我经常看到的这种代码模式:
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]
很明显,变量没有在初始化中使用,只有其类型才使用。有没有一种方法可以避免这种警告,而无需处理每个编译器实用程序的地狱?
编辑:
从我最初的帖子中还不清楚,但是当我写SomeComplexTypeNotAuto
时,我的意思是这样的代码:auto a = foo.as2(a);
无法解析,因为您have提供了一种允许编译器推断的类型。
我的问题是特定于方法as2()
是模板的事实,因此对于类型T
,它必须在专门化时可见。因此,编译器可以看到参数T*
甚至都没有名称,因此在函数内部无法使用/使用。因此,我不明白为什么它警告“未使用的变量”警告,因为很明显它没有被使用。
很明显,变量未在初始化中使用
相反,很明显,在函数参数的初始化中使用了变量is。该程序的行为是不确定的。
这是不正确的警告吗?
否,警告是正确的。
一个简单的解决方法是将参数更改为引用:
T* as2(T*&)
请特别确保不要实际读取参考值。
自C + 11起,但是您可以改用auto
。
警告正确。
[a
]在其自己的初始化程序中具有未指定的值,并且按值将其作为函数参数传递要求复制它,这需要对其进行读取,这具有未定义的行为。
不要紧接着不使用原来的结果值。
您可以通过防止复制(带有按引用参数)来“修复”它,但是最终将得到非常奇怪和不寻常的代码,这会使读者感到困惑。我真的不建议这种方法。
只需拼出类型,理想情况下首先使其更短并且更易读。
通常,我们跳过这样的重复类型名称:
auto* a = foo.as1<SomeComplexTypeAndNotAuto>();
(例如,使用std::make_shared
和朋友时]
也请查看访客模式。
尚不清楚在初始化期间未使用该变量。 as2
内部可能发生任何事情。
如果未使用该变量,则不要传递它-请使用显式模板实例化。