如何根据模板参数为不同类型变量创建统一引用别名?
解决C++中基于模板常量创建不同类型变量别名的问题
问题代码
Type1 myVarWithAVeryLongName1 = new Type1(); // 实际是指针链,这里简化示意 Type2 myVarWithAVeryLongName2 = new Type2(); template<bool usesType2> void func() { // auto& myVar = usesType2 ? myVarWithAVeryLongName2 : myVarWithAVeryLongName1; // 三元表达式无法返回不同类型 /*if constexpr (usesType2) { auto& myVar = myVarWithAVeryLongName2; } else { auto& myVar = myVarWithAVeryLongName1; } // 别名会超出作用域 */ auto& myVar = ?; // … 后续大量重复操作代码 }
需求说明
需要对myVarWithAVeryLongName1和myVarWithAVeryLongName2执行几乎相同的操作,由于操作代码量大且Type1与Type2高度相似,想用单个函数配合if constexpr减少约300行重复代码,但创建统一引用别名myVar时遇到了问题,求可行方案。
可行实现方式
方法1:模板辅助函数获取引用
写一个小型模板辅助函数,根据模板参数返回对应变量的引用,这样就能在func内拿到全局有效的myVar别名:
Type1 myVarWithAVeryLongName1 = new Type1(); Type2 myVarWithAVeryLongName2 = new Type2(); // 辅助函数:编译期确定返回的引用类型 template<bool usesType2> auto& getMyVar() { if constexpr (usesType2) { return myVarWithAVeryLongName2; } else { return myVarWithAVeryLongName1; } } template<bool usesType2> void func() { auto& myVar = getMyVar<usesType2>(); // 后续所有操作直接用myVar即可,作用域覆盖整个func // … }
这个方法靠if constexpr在编译阶段就敲定返回类型,没有任何运行时开销,逻辑清晰易维护。
方法2:用std::conditional统一类型
借助<type_traits>里的std::conditional_t,在编译期推导引用类型,再用三元表达式赋值:
#include <type_traits> Type1 myVarWithAVeryLongName1 = new Type1(); Type2 myVarWithAVeryLongName2 = new Type2(); template<bool usesType2> void func() { // 编译期确定引用类型 using VarType = std::conditional_t<usesType2, Type2&, Type1&>; // 此时三元表达式两边类型会匹配到VarType,编译通过 VarType myVar = usesType2 ? myVarWithAVeryLongName2 : myVarWithAVeryLongName1; // … 后续操作 }
注意:这个方法要求Type1和Type2之间能隐式转换(题目说二者高度相似,应该满足这个条件),如果是完全无关的类型可能不适用。
方法3:立即调用的lambda表达式
用一个立即执行的lambda在内部做if constexpr判断,直接返回对应引用,这样myVar的作用域就能覆盖整个func:
Type1 myVarWithAVeryLongName1 = new Type1(); Type2 myVarWithAVeryLongName2 = new Type2(); template<bool usesType2> void func() { auto& myVar = [&]() -> auto& { if constexpr (usesType2) { return myVarWithAVeryLongName2; } else { return myVarWithAVeryLongName1; } }(); // 立即调用lambda // … 后续操作 }
这种方式不需要额外写辅助函数,把逻辑封装在lambda里,代码紧凑。
内容的提问来源于stack exchange,提问作者IDontKnowWhatToPutAsMyUsername
相关产品推荐
相关产品推荐

