我想要一个能够以任何顺序获取多个参数的组合功能。 例如:
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')
因为为每个案例创建一个函数是很乏味的,特别是当你有很多参数并且你想要任何顺序时。
这有可能吗?
答案 0 :(得分:6)
您可以使用功能模板:
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
有效的任何类型。
答案 1 :(得分:5)
您可以将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
的返回类型。
答案 2 :(得分:0)
你有两种方式:
1 - 您可以重载该功能 - &gt;这是一个糟糕的方式
2 - 你可以使用模板 - &gt;我推荐它
答案 3 :(得分:0)
您可以重载该函数,但只有一个“base”函数可以在其他函数中调用,例如:
// "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;
}
答案 4 :(得分:0)
在其他答案中没有人提到它,所以我只想重申我在评论中说的话。 您想要从一组对象构建一些东西,其顺序未指定。我认为你对builder pattern
的变体做得很好您的案例中不需要抽象构建器。只需要一个带有一堆add
成员函数的累加器对象,用于您想要支持的类型。在循环中添加',然后从累加器中获取结果。
如果你的类型确实只是基本积分和浮点值,只需写出循环并直接进行加法。
答案 5 :(得分:0)
以下可能会有所帮助:
它使用模板和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;
}