当结构具有成员时,在模板函数中访问该成员

时间:2019-12-17 08:58:10

标签: c++ templates

我想用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;
}

约束:我无法更改FooBar,因此例如不能为Foo添加抽象接口超类。我也不想专门针对任何命名类使用该函数,也不想重复任何逻辑代码。

我目前比较愚蠢的解决方案是拥有template <typename T> int helperFunc(const T &item, int y = 0) {...};,然后像Foo那样叫helperFunct(aFoo, aFoo.y),这对我的用例是有效的,但不是很好。我想决定在模板中使用y。我试图从here中找到适用的内容,但实际上并没有想出一种使用任何一种方法来实现以上目标的方法。

2 个答案:

答案 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;

LIVE