在 temporary 之前调用的析构函数应该超出范围
destructor called before temporary should be out of scope
我有一些代码在 VS2015 下失败,但在 GCC 下工作。我很确定错误与 Visual Studio 有关,但想确保我对 decltype(auto) 的理解是正确的。
#include <iostream>
using namespace std;
string zero_params()
{
return "zero_params called.";
}
template< typename F >
auto test1( F f ) -> decltype(auto)
{
return f();
}
int main() {
cout << std::is_rvalue_reference< decltype(test1(zero_params)) >::value << endl;
cout << test1(zero_params) << endl;
cout << "Done!" << endl;
return 0;
}
在 Visual Studio 下,由 zero_params 编辑的字符串 return 被推断为右值引用。此外,该对象的析构函数在 test1() 内部被调用,其中 return 从调用 f 发生(这似乎是一个合理的地方来破坏 && 对象)。
在 GCC 下,字符串 returned 不会被推断为右值引用。如我所料,在 cout 语句中使用后调用析构函数。
将 return 类型指定为 'string' 而不是 Visual Studio 下的 decltype(auto) 修复它,就像在 return 上使用 remove_reference_t 一样test1.
中的 f()
我的期望是 GCC 是正确的,因为 zero_params() 的函数签名是字符串,而不是字符串&& 所以我希望 'bubble up' 不会引用 return test1 的类型,如果它使用 decltype(auto)。
这是正确的评估吗?
后期编辑:
我发现使用 VS2015 解决此问题的另一种方法是将提供给 test1 的函数包装在 lambda 中:
cout << test1(zero_params) << endl;
至:
cout << test1( [](auto&&... ps) { return zero_params(std::forward<decltype(ps)>(ps)...); } ) << endl;
所以based on the comments我们可以得出结论:
- 这是 VS2015 预览中的错误
- 有解决方法
- bug has been reported
错误在于:
- 编译器应该推断出 return 类型为字符串
- 居然推导出是字符串&&
- 因此它过早地破坏了价值
解决方法是:
- 不要对函数的 return 类型使用 decltype(auto)
- 在传入之前将函数包装在 lambda 表达式中
我有一些代码在 VS2015 下失败,但在 GCC 下工作。我很确定错误与 Visual Studio 有关,但想确保我对 decltype(auto) 的理解是正确的。
#include <iostream>
using namespace std;
string zero_params()
{
return "zero_params called.";
}
template< typename F >
auto test1( F f ) -> decltype(auto)
{
return f();
}
int main() {
cout << std::is_rvalue_reference< decltype(test1(zero_params)) >::value << endl;
cout << test1(zero_params) << endl;
cout << "Done!" << endl;
return 0;
}
在 Visual Studio 下,由 zero_params 编辑的字符串 return 被推断为右值引用。此外,该对象的析构函数在 test1() 内部被调用,其中 return 从调用 f 发生(这似乎是一个合理的地方来破坏 && 对象)。
在 GCC 下,字符串 returned 不会被推断为右值引用。如我所料,在 cout 语句中使用后调用析构函数。
将 return 类型指定为 'string' 而不是 Visual Studio 下的 decltype(auto) 修复它,就像在 return 上使用 remove_reference_t 一样test1.
中的 f()我的期望是 GCC 是正确的,因为 zero_params() 的函数签名是字符串,而不是字符串&& 所以我希望 'bubble up' 不会引用 return test1 的类型,如果它使用 decltype(auto)。
这是正确的评估吗?
后期编辑:
我发现使用 VS2015 解决此问题的另一种方法是将提供给 test1 的函数包装在 lambda 中:
cout << test1(zero_params) << endl;
至:
cout << test1( [](auto&&... ps) { return zero_params(std::forward<decltype(ps)>(ps)...); } ) << endl;
所以based on the comments我们可以得出结论:
- 这是 VS2015 预览中的错误
- 有解决方法
- bug has been reported
错误在于:
- 编译器应该推断出 return 类型为字符串
- 居然推导出是字符串&&
- 因此它过早地破坏了价值
解决方法是:
- 不要对函数的 return 类型使用 decltype(auto)
- 在传入之前将函数包装在 lambda 表达式中