【发布时间】:2020-08-11 05:08:41
【问题描述】:
最近我一直在尝试学习右值和完美转发。在玩弄一些结构时,我在切换编译器和优化级别时遇到了一些特殊的行为。
在没有开启优化的情况下在 GCC 上编译相同的代码会产生预期的结果,但是开启任何优化级别会导致我的所有代码都被删除。 在没有优化的情况下在 clang 上编译相同的代码也会产生预期的结果。然后在 clang 上开启优化仍然会产生预期的结果。
我知道这会导致未定义的行为,但我就是无法弄清楚到底出了什么问题以及是什么导致了两个编译器之间的差异。
gcc -O0 -std=c++17 -Wall -Wextra
gcc -O3 -std=c++17 -Wall -Wextra
clang -O0 -std=c++17 -Wall -Wextra
clang -O3 -std=c++17 -Wall -Wextra
#include <utility>
// lambda_t is the type of thing we want to call.
// capture_t is the type of a helper object that
// contains all all parameters meant to be passed to the callable
template< class lambda_t, class capture_t >
struct CallObject {
lambda_t m_lambda;
capture_t m_args;
typedef decltype( m_args(m_lambda) ) return_t;
//Construct the CallObject by perfect forwarding which is
//neccessary as they may these are lambda which will have
//captured objects and we dont want uneccessary copies
//while passing these around
CallObject( lambda_t&& p_lambda, capture_t&& p_args ) :
m_lambda{ std::forward<lambda_t>(p_lambda) },
m_args { std::forward<capture_t>(p_args) }
{
}
//Applies the arguments captured in m_args to the thing
//we actually want to call
return_t invoke() {
return m_args(m_lambda);
}
//Deleting special members for testing purposes
CallObject() = delete;
CallObject( const CallObject& ) = delete;
CallObject( CallObject&& ) = delete;
CallObject& operator=( const CallObject& ) = delete;
CallObject& operator=( CallObject&& ) = delete;
};
//Factory helper function that is needed to create a helper
//object that contains all the paremeters required for the
//callable. Aswell as for helping to properly templatize
//the CallObject
template< class lambda_t, class ... Tn >
auto Factory( lambda_t&& p_lambda, Tn&& ... p_argn ){
//Using a lambda as helper object to contain all the required paramters for the callable
//This conviently allows for storing value, references and so on
auto x = [&p_argn...]( lambda_t& pp_lambda ) mutable -> decltype(auto) {
return pp_lambda( std::forward<decltype(p_argn)>(p_argn) ... );
};
typedef decltype(x) xt;
//explicit templetization is not needed in this case but
//for the sake of readability it needed here since we then
//need to forward the lambda that captures the arguments
return CallObject< lambda_t, xt >( std::forward<lambda_t>(p_lambda), std::forward<xt>(x) );
}
int main(){
auto xx = Factory( []( int a, int b ){
return a+b;
}, 10, 3 );
int q = xx.invoke();
return q;
}
【问题讨论】:
-
I know this screams undefined behavior but i just cannot figure out what exactly is going wrong你说那句话出了什么问题。程序的行为未定义。 -
但是为什么呢?我想了解我做错了什么。即使使用 -Wall -Wextra 也没有给我警告
标签: c++