能否在C++三元条件运算符的首个操作数内定义变量?
核心结论
从C98到最新的C23正式标准,都不支持在三元(条件)运算符的操作数内部直接定义临时变量,你设想的带分号的写法属于语法规则不允许的结构,所有标准版本的编译器都会直接报语法错误。
普通if语句支持在判断条件中定义变量,本质是语法层面给if预留了语句级的插入位置:从C98开始就支持if (int foo = 10)的写法,C17之后还进一步扩展了if (init_statement; condition)的形式,本质是把初始化逻辑作为独立的语句块和分支判断绑定。但三元运算符的语法定义是严格的纯表达式结构,三个位置都只能放置可以计算出单个值的表达式,不允许插入带分号的语句序列、变量声明这类语句级结构,自然无法实现你设想的内嵌定义写法。
无第三方依赖的原生替代方案
有几种不需要额外库就能达到同等效果的写法,从简单到灵活分别是:
- 最基础的实现:把临时变量移到三元运算前定义,通过匿名作用域限制变量的生命周期,避免污染外层命名空间
std::string result; { // 临时变量foo的作用域被完全限制在当前块内 const int foo = 10; result = (foo > 9 ? "larger than 9" : "less than 10"); } - 更贴合表达式写法的方案:C++11及以上版本可以用立即调用的lambda表达式,把所有判断逻辑和临时变量封装在单条表达式语句里,完全没有作用域泄漏的问题
如果需要在判断前做多步复杂计算,也可以把中间变量直接定义在lambda内部,灵活性很高,写法上也更接近你想要的“变量定义内嵌在判断逻辑里”的效果。std::string result = [](int temp_val) { // 所有临时变量的生命周期都被lambda隔离 return temp_val > 9 ? "larger than 9" : "less than 10"; }(10);
基于Boost的实现方案
如果习惯更接近你最初设想的语法形态,可以使用Boost生态里的表达式模板库实现对应效果:
- 借助Boost.Phoenix的
let子句,可以直接在嵌套的表达式结构里定义临时局部变量,变量的作用域完全被限制在后续的表达式块内,不会泄漏到外层,语法上和你想要的“在三元判断前定义临时变量”的体验基本一致:#include <boost/phoenix.hpp> using namespace boost::phoenix; std::string result = ( // let子句内嵌定义临时变量_a,值为10 let(local::_a = 10)[ local::_a > 9 ? val("larger than 9") : val("less than 10") ] )();
内容的提问来源于stack exchange,提问作者J'e
相关产品推荐
相关产品推荐

