我得到以下warning: parameter 'tupleValue' set but not used [-Wunused-but-set-parameter]
,但该参数在return语句中显式使用。
它是否真的意味着在调用序列的后面某处忽略返回值,编译器是否足够酷以在此行上优化它?
这是代码:
template<unsigned int ...Vs, class ...Ts>
typename removeLastType<Ts...>::type internalRemoveData(intValues<Vs...>, std::tuple<Ts...> tupleValue)
{
return std::forward_as_tuple(std::get<Vs>(tupleValue)...);
}
完整来源位于:https://github.com/copperspice/cs_signal/blob/master/src/cs_internal.h#L316
在Windows中编译:
-- The C compiler identification is GNU 5.3.0
-- The CXX compiler identification is GNU 5.3.0
答案 0 :(得分:3)
实际上不是答案,但你的代码中有未定义的行为,正如@RinatVeliakhmedov指出的那样。 internalRemoveData
函数的返回值是std::tuple
,由悬空引用组成,即对不再存在的对象的引用。
考虑以下简化案例:
struct X {
X() { std::cout << "def ctor\n"; }
~X() { std::cout << "dtor\n"; }
void f() { std::cout << "f\n"; }
};
template<int ...Is, class ...Ts>
auto f(std::tuple<Ts...> t) {
return std::forward_as_tuple(std::get<Is>(t)...);
}
int main() {
auto res = f<0>(std::tuple<X>{});
std::cout << "---" << std::endl;
// std::get<0>(res).f(); // would use no-longer existing object
}
此程序打印出来:
def ctor
dtor
---
f
函数完成后,不再存在X
的任何对象。
请注意,此问题可能非常危险,因为程序可以按预期运行。我在Wandbox中使用未注释的std::get<0>(res).f();
语句尝试了它,程序打印出f
并且没有显示任何错误。未定义的行为也包括预期的行为。
答案 1 :(得分:1)
作为原始代码的作者之一,我认为这里的行为定义明确,但原因有点微妙。这是我的逻辑。如果我错过了什么,那就让我们继续讨论。
internalRemoveData方法接收一个值元组,并返回一个具有完全相同数据类型的值元组,减去最后一个元素。分别考虑元组中的每个元素,只有三种可能的情况很重要。
如果元素是值类型,则forward_as_tuple函数将产生左值引用。此左值引用将分配给返回元组的相应元素,这是一个值类型。这将从输入复制到输出,没有悬空参考。
如果元素是左值引用,则它必须已经是对某个有效原始对象的引用。它将作为左值引用转发,然后绑定到输出中相应的左值引用。
如果元素是右值引用,它也必须已经是对某个有效原始对象的引用。我们得到与左值参考案例相同的行为。
关键是看到返回类型不与forward_as_tuple返回的类型相同。
如果此问题已关闭,请在我们的YouTube频道上查询原始问题:https://www.youtube.com/watch?v=uK-2jzB41c4