简体   繁体   English

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

[英]Accessing struct member in a template function, when the struct has that member

I'd like to implement this functionality with C++ templates as nicely as possible.我想用 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;
}

Constraints: I can not alter Foo or Bar , so I can't for example add abstract interface superclass for Foo .约束:我不能改变FooBar ,所以我不能例如为Foo添加抽象接口超类。 I don't want to specialize the function specifically for any named class either, and I don't want to repeat any logic code.我也不想专门为任何命名类专门化该函数,也不想重复任何逻辑代码。

My current, rather dumb solution is to have template <typename T> int helperFunc(const T &item, int y = 0) {...};我目前相当愚蠢的解决方案是让template <typename T> int helperFunc(const T &item, int y = 0) {...}; , and then for a Foo call it like helperFunct(aFoo, aFoo.y) , which works for my use case, but is not very nice. ,然后对于Foo调用它像helperFunct(aFoo, aFoo.y) ,这适用于我的用例,但不是很好。 I'd like to put the decision to use y inside the template.我想将使用y的决定放在模板中。 I tried to find something applicable from here , but couldn't really come up with a way to use any of that to achieve the above.我试图从这里找到一些适用的东西,但无法真正想出一种方法来使用其中任何一种来实现上述目标。

You can use SFINAE on function overloads to check for the existence of y , then use if-constexpr :您可以在函数重载上使用 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;
}

You can make type trait to check whether the type has the member y or not.您可以使用 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 {};

then you can apply constexpr if (since C++17).那么你可以应用constexpr if (C++17 起)。

if constexpr (has_y<T>::value) // only do code below if item has y
    result += item.y;

LIVE居住

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM