如何从单个 C++ return 语句中 return 多个值中的一个?
How to return one out of multiple values from a single C++ return statement?
return a or b or c or d;
该语句 return 在 C++ 中是 true
或 false
,我知道这样做的原因。
但我需要一个解决方法,以便我可以 return 第一个 非零 值 通过那个 return 语句(或类似的东西)就像它发生在 Python.
我不是在寻找条件语句,因为它看起来不整洁 sometimes。
基本上,可以通过宏或其他方式缩短以下代码吗?
int fun(int a, int b, int c, int d)
{
return a ? a : b ? b : c ? c : d;
}
任务可以通过在return语句中使用必要的函数来完成。
例如,我没有使用宏,而是使用了 模板函数,它接受 std::initializer_list
:
中的参数
template <typename T>
T OR(const std::initializer_list<T>& args)
{
for (const T& arg : args)
if (arg)
return arg;
return T{};
}
对于给定的问题,可以按如下方式使用:
return OR({a, b, c, d});
那个link的问题也可以这样解决:
return OR({(m + s - 1) % n, n});
请注意,它取决于给定类型的隐式布尔转换 T
。因此,例如 an empty std::string
is not false
。此外,用户定义的类型应具有 operator bool() const
以符合此解决方法。
P.S。当我试图在问题的可变参数模板解决方案中询问我的错误时,我自己发现了这个解决方案:P
注:
请参阅 答案以了解这种方式在处理更复杂的设计时的局限性。
我会这样写函数:
int fun(int a, int b, int c, int d) {
if (a) return a;
else if (b) return b;
else if (c) return c;
return d;
}
它干净而简短。我可以在这里停下来,但让我们探索可以做什么...
存在一种几乎可以满足您要求的算法。 中的解决方案略作修改:
#include <algorithm>
#include <initializer_list>
template <typename T>
T first_non_zero_or_zero(const std::initializer_list<T>& args)
{
auto it = std::find_if_not(args.begin(),args.end(),[](auto v){ return v==0;});
return (it != args.end()) ? *it : 0;
}
对布尔表达式使用函数的缺点是没有捷径。如果您通过以下方式调用函数:
auto x = first_non_zero_or_zero( { foo(), expensive_function() });
则必须调用expensive_function
,不管foo
return是什么。恢复短路能力的方法是传递可调用对象,即
template <typename F>
auto first_non_zero_or_zero(F f){ return f();}
template <typename First,typename...F>
auto first_non_zero_or_zero(First f,F... others){
if (auto temp = f()) return temp;
return first_non_zero_or_zero(others...);
}
int foo(){ return 0;}
int expensive_function(){ return 42;}
int main()
{
std::cout << first_non_zero_or_zero(foo,expensive_function);
return 0;
}
但是,当使用简单的 int
s 调用时,这会使调用变得不必要的冗长,因为您需要将它们包装在可调用的文件中:
int fun(int a,int b,int c) {
first_non_zero( [](){ return a;},
[](){ return b;},
[](){ return c;})
}
结论:不要让事情变得不必要的复杂。函数应该做一件事。您的 fun
所做的一件事是 return 4 个整数中的第一个非零整数,而 if-else
是完成该操作的最简单方法。
return a or b or c or d;
该语句 return 在 C++ 中是 true
或 false
,我知道这样做的原因。
但我需要一个解决方法,以便我可以 return 第一个 非零 值 通过那个 return 语句(或类似的东西)就像它发生在 Python.
我不是在寻找条件语句,因为它看起来不整洁 sometimes。
基本上,可以通过宏或其他方式缩短以下代码吗?
int fun(int a, int b, int c, int d)
{
return a ? a : b ? b : c ? c : d;
}
任务可以通过在return语句中使用必要的函数来完成。
例如,我没有使用宏,而是使用了 模板函数,它接受 std::initializer_list
:
template <typename T>
T OR(const std::initializer_list<T>& args)
{
for (const T& arg : args)
if (arg)
return arg;
return T{};
}
对于给定的问题,可以按如下方式使用:
return OR({a, b, c, d});
那个link的问题也可以这样解决:
return OR({(m + s - 1) % n, n});
请注意,它取决于给定类型的隐式布尔转换 T
。因此,例如 an empty std::string
is not false
。此外,用户定义的类型应具有 operator bool() const
以符合此解决方法。
P.S。当我试图在问题的可变参数模板解决方案中询问我的错误时,我自己发现了这个解决方案:P
注:
请参阅
我会这样写函数:
int fun(int a, int b, int c, int d) {
if (a) return a;
else if (b) return b;
else if (c) return c;
return d;
}
它干净而简短。我可以在这里停下来,但让我们探索可以做什么...
存在一种几乎可以满足您要求的算法。
#include <algorithm>
#include <initializer_list>
template <typename T>
T first_non_zero_or_zero(const std::initializer_list<T>& args)
{
auto it = std::find_if_not(args.begin(),args.end(),[](auto v){ return v==0;});
return (it != args.end()) ? *it : 0;
}
对布尔表达式使用函数的缺点是没有捷径。如果您通过以下方式调用函数:
auto x = first_non_zero_or_zero( { foo(), expensive_function() });
则必须调用expensive_function
,不管foo
return是什么。恢复短路能力的方法是传递可调用对象,即
template <typename F>
auto first_non_zero_or_zero(F f){ return f();}
template <typename First,typename...F>
auto first_non_zero_or_zero(First f,F... others){
if (auto temp = f()) return temp;
return first_non_zero_or_zero(others...);
}
int foo(){ return 0;}
int expensive_function(){ return 42;}
int main()
{
std::cout << first_non_zero_or_zero(foo,expensive_function);
return 0;
}
但是,当使用简单的 int
s 调用时,这会使调用变得不必要的冗长,因为您需要将它们包装在可调用的文件中:
int fun(int a,int b,int c) {
first_non_zero( [](){ return a;},
[](){ return b;},
[](){ return c;})
}
结论:不要让事情变得不必要的复杂。函数应该做一件事。您的 fun
所做的一件事是 return 4 个整数中的第一个非零整数,而 if-else
是完成该操作的最简单方法。