C++同时初始化引用和赋值变量



我的代码中有这一部分,我在同一布尔条件下使用if-else和三元运算符。有更优雅的方法吗?

bool UseGroups //input parameter to a function.
std::vector<std::vector<int>>& relevantGamesGroup = (useGroups) ? (objFlight.gamesGroup[dayIndex]) : (objFlight.gamesSubGroups[dayIndex]);
if (useGroups) {
numberOfGroups = objFlight.numberOfGroups[dayIndex];
}
else {
numberOfGroups = 2 * (objFlight.numberOfGroups[dayIndex]);
}

我可能会这样写,因为我发现读起来很清楚:

auto& relevantGamesGroup = useGroups
? objFlight.gamesGroup[dayIndex]
: objFlight.gamesSubGroups[dayIndex];
auto numberOfGroups = useGroups
? objFlight.numberOfGroups[dayIndex]
: objFlight.numberOfGroups[dayIndex] * 2;

如果只检查了一次条件就需要使用变量relevantGamesGroupnumberOfGroups,则可以创建并调用一个临时lambda,使其返回必要的对:

auto&& [relevantGamesGroup, numberOfGroups] =
[&]() -> std::pair<std::vector<std::vector<int>>&, int>
{
if (useGroups) return {objFlight.gamesGroup[dayIndex],
objFlight.numberOfGroups[dayIndex]};
return {objFlight.gamesSubGroups[dayIndex],
2 * objFlight.numberOfGroups[dayIndex]};
}();
// use relevantGamesGroup and numberOfGroups here

使用三元/条件运算符而不是使用lambda:的替代方法

auto&& [relevantGamesGroup, numberOfGroups] =
useGroups ? std::pair<std::vector<std::vector<int>>&, int>
{objFlight.gamesGroup[dayIndex],
objFlight.numberOfGroups[dayIndex]}
: std::pair<std::vector<std::vector<int>>&, int>
{objFlight.gamesSubGroups[dayIndex],
2 * objFlight.numberOfGroups[dayIndex]};
// use relevantGamesGroup and numberOfGroups here

如果你经常使用这种构造,创建一个辅助函数可以简化它:

#include <tuple>
template<class... Ts>
std::tuple<Ts...> ternary(bool cond, std::tuple<Ts...>&& True,
std::tuple<Ts...>&& False) {
return cond ? True : False;
}

然后,您可以提供所需的类型作为模板参数,并使用结构化绑定来提取所选的值/引用,就像上面一样:

int main() {
int a1 = 1, b1 = 2, c1 = 3;
int a2 = 40, b2 = 50, c2 = 60;
auto&&[a,b,c] = ternary<int&,int&,int&>(true, {a1,b1,c1}, {a2,b2,c2});
std::cout << a << b << c << 'n';
++a; ++b; ++c; // these are references to a1, b1 and c1
std::cout << a1 << b1 << c1 << 'n';
}

输出:

123
234

对于你问题中的类型,它可能看起来像这样:

void func(bool useGroups) {
auto&& [relevantGamesGroup, numberOfGroups] =
ternary<std::vector<std::vector<int>>&, int>(useGroups,
{objFlight.gamesGroup[dayIndex],     objFlight.numberOfGroups[dayIndex]},
{objFlight.gamesSubGroups[dayIndex], 2 * objFlight.numberOfGroups[dayIndex]});
// use relevantGamesGroup and numberOfGroups here
}

不确定是否更多"优雅";,但是,如果你坚持只写一个if/else,那么要么使用指针而不是relevantGamesGroup的引用,后者可以默认初始化并稍后分配,要么lambda可以帮助:

auto& relevantGamesGroup = [&]()->decltype(auto){
if (useGroups) {
numberOfGroups = objFlight.numberOfGroups[dayIndex];
return objFlight.gamesGroup[dayIndex];
} else {
numberOfGroups = 2 * (objFlight.numberOfGroups[dayIndex]);
return objFlight.gamesSubGroups[dayIndex];
}
}();

(请注意,->decltype(auto)在这里很重要,因为lambda将按值返回,而不是按引用返回。(

为了完整性,只使用一个三元运算符的方法显然更糟糕:

auto& relevantGamesGroup = useGroups
? ((void)(numberOfGroups = objFlight.numberOfGroups[dayIndex]),
objFlight.gamesGroup[dayIndex])
: ((void)(numberOfGroups = 2 * (objFlight.numberOfGroups[dayIndex])), 
objFlight.gamesSubGroups[dayIndex]);

(如果你没有为numberOfGroups使用一些非常奇怪的类型,(void)强制转换是可选的(

这段代码对我来说很好。下面是我如何重写它,但主要是风格问题。

bool useGroups;
// Use of auto
auto& relevantGamesGroup = useGroups ? objFlight.gamesGroup[dayIndex] : objFlight.gamesSubGroups[dayIndex];
numberOfGroups = objFlight.numberOfGroups[dayIndex];
if (useGroups) {
numberOfGroups *= 2;
}

这是干净的,如果需要,可以由实习生Joe修复。

using GroupGames = std::vector<std::vector<int>>;
GroupGames* relevantGamesGroup; 
if (useGroups) { 
relevantGamesGroup = &objFlight.gamesGroup[dayIndex];
}
else {
relevantGamesGroup = &objFlight.gamesSubGroups[dayIndex];
}
if (useGroups) {
numberOfGroups = objFlight->numberOfGroups[dayIndex];
}
else {
numberOfGroups = 2 * (objFlight->numberOfGroups[dayIndex]);
}

或者在下面@Ted Lyngmo的建议下,它甚至更干净。

using GroupGames = std::vector<std::vector<int>>;
GroupGames* relevantGamesGroup = &objFlight.gamesSubGroups[dayIndex];
int numberOfGroups = 2 * (objFlight->numberOfGroups[dayIndex]);
if (useGroups) { 
relevantGamesGroup = &objFlight.gamesGroup[dayIndex];
numberOfGroups = objFlight->numberOfGroups[dayIndex];
}

最新更新