我想用C ++模板尽可能好地实现此功能。
struct Foo {
int x = 0;
int y = 0;
};
struct Bar {
int x = 1;
};
// I want to call this function for both Foo and Bar instances
template <typename T>
int helperFunc(const T &item) {
// many lines of code I don't want to repeat
int result = item.x;
result += item.x;
result *= item.x;
// only do code below if item has y
result += item.y;
return result;
}
约束:我无法更改Foo
或Bar
,因此例如不能为Foo
添加抽象接口超类。我也不想专门针对任何命名类使用该函数,也不想重复任何逻辑代码。
我目前比较愚蠢的解决方案是拥有template <typename T> int helperFunc(const T &item, int y = 0) {...};
,然后像Foo
那样叫helperFunct(aFoo, aFoo.y)
,这对我的用例是有效的,但不是很好。我想决定在模板中使用y
。我试图从here中找到适用的内容,但实际上并没有想出一种使用任何一种方法来实现以上目标的方法。
答案 0 :(得分:4)
您可以在函数重载上使用SFINAE来检查y
的存在,然后使用if-constexpr
:
template <typename T>
std::true_type hasY_ (decltype(std::declval<T> ().y)*);
template <typename T>
std::false_type hasY_ (...);
template <typename T>
static constexpr bool hasY = decltype(hasY_<T>(0))::value;
// I want to call this function for both Foo and Bar instances
template <typename T>
int helperFunc(const T &item) {
// many lines of code I don't want to repeat
int result = item.x;
result += item.x;
result *= item.x;
// only do code below if item has y
if constexpr (hasY<T>)
result += item.y;
return result;
}
答案 1 :(得分:2)
您可以使type trait检查类型是否具有成员y
。
template <typename T, typename = void>
struct has_y : std::false_type {};
template <typename T>
struct has_y<T, std::void_t<decltype(std::declval<T>().y)>>
: std::true_type {};
然后您可以应用constexpr if(自C ++ 17起)。
if constexpr (has_y<T>::value)
result += item.y;