我可以在 C++ 中使用无序函数参数吗?
can i have unordered function arguments in c++?
我想要一个组合函数,它以任何顺序接受多个参数。例如:
int combine(int a, float b, char c)
{
return a+b+c;
}
这只是我想做的一个例子,但我希望能够使用任何参数顺序调用这个函数:combine(1,2.5,'c')
或combine('c', 1 2.5)
或combine(2.5,1,'c')
因为为每个案例创建一个函数是乏味的,尤其是当您有很多参数并且您希望按任何顺序排列它们时。这可能吗?
您可以使用函数模板:
template <typename T1, typename T2, typename T3>
int combine(T1 a, T2 b, T3 c)
{
return a+b+c;
}
请注意,这将a
、b
和c
加法表达式a+b+c
有效的任何类型。
您可以将combine()
设为函数模板
template <typename T0, typename T1, typename T2>
int combine(T0 a0, T1 a1, T2 a2) {
return a0 + a1 + a2;
}
如果要限制可以传递的类型,可以使用 SFINAE 添加约束。不过,将参数限制为类型 char
、 int
和 float
类型,尤其是在应该允许标准转换的情况下,并非完全微不足道。我认为它看起来像这样:
#include <type_traits>
template <typename T>
struct is_allowed
: std::integral_constant<bool,
std::is_convertible<T, char>::value
|| std::is_convertible<T, int>::value
|| std::is_convertible<T, float>::value> {
};
template <typename T0, typename T1, typename T2>
typename std::enable_if<
is_allowed<T0>::value && is_allowed<T1>::value && is_allowed<T2>::value,
int>::type combine(T0 a0, T1 a1, T2 a2) {
return a0 + a1 + a2;
}
如果您实际上也想保留小数部分(如果存在),您可能需要查看返回类型的std::common_type<T0, T1, T2>::type
。
您有两种方法:
1-你可以重载函数 ->这是一种不好的方式
2-您可以使用模板 ->我推荐它
在其他答案中没有人提到它,所以我只是重申我在评论中所说的。您希望从一组对象构建某些内容,其顺序未指定。我认为你会很好地使用构建器模式的变体
在你的情况下,你不需要抽象构建器。只需有一个累加器对象,其中包含一堆add
成员函数,用于要支持的类型。在循环中添加它们,然后从累加器中获取结果。
如果您的类型确实只是基元积分和浮点值,只需写出循环并直接执行加法即可。
你可以重载该函数,但有一个"基"函数,在其他函数中被调用,例如:
// "base" function:
int combine(int a, float b, char c)
{
return a+b+c;
}
// define "forwarders" for reordered function types:
inline int combine(float b, int a, char c) { return combine(a, b, c); }
inline int combine(int a, char c, float b) { return combine(a, b, c); }
inline int combine(float b, char c, int a) { return combine(a, b, c); }
inline int combine(char c, int a, float b) { return combine(a, b, c); }
inline int combine(char c, float b, int a) { return combine(a, b, c); }
正如您在评论中告诉我们的,您希望使用三种类型的另一种组合来进一步重载它;因此您可以考虑将定义重载的五行包装在宏中:
#define OVERLOAD_REORDERED(Treturn, functionName, T1, T2, T3)
inline Treturn functionName(T2 b, T1 a, T3 c) { return functionName(a, b, c); }
inline Treturn functionName(T1 a, T3 c, T2 b) { return functionName(a, b, c); }
inline Treturn functionName(T2 b, T3 c, T1 a) { return functionName(a, b, c); }
inline Treturn functionName(T3 c, T1 a, T2 b) { return functionName(a, b, c); }
inline Treturn functionName(T3 c, T2 b, T1 a) { return functionName(a, b, c); }
然后只写:
int combine(int a, float b, char c)
{
return a+b+c;
}
OVERLOAD_REORDERED(int, combine, int, float, char)
由于您可能将其拆分为声明 (.h) 和定义 (.cpp),因此您可以将宏调用放在标头中,如下所示:
// .h:
int combine(int a, float b, char c);
OVERLOAD_REORDERED(int, combine, int, float, char)
// .cpp:
int combine(int a, float b, char c)
{
return a+b+c;
}
以下内容可能会有所帮助:
它使用模板和SFINAE。
这个SFINAE是每个类型正好有一次。
template <typename T, typename ...Ts> struct count_type;
template <typename T, typename Tail, typename ...Ts>
struct count_type<T, Tail, Ts...>
{
constexpr static int value = std::is_same<T, Tail>::value + count_type<T, Ts...>::value;
};
template <typename T> struct count_type<T>
{
constexpr static int value = 0;
};
template <typename T0, typename T1, typename T2>
typename std::enable_if<count_type<int, T0, T1, T2>::value == 1
&& count_type<float, T0, T1, T2>::value == 1
&& count_type<int, T0, T1, T2>::value == 1, int>::type
combine(T0 a0, T1 a1, T2 a2) {
return a0 + a1 + a2;
}
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数