在C ++中,如何从数组中提取成员并返回该成员类型的数组?

时间:2018-08-24 19:59:21

标签: c++ arrays templates preprocessor

namespace detail
{
    template <typename T, typename U>
    Array<U> extract_(const Array<T>& array, std::function<U(const T&)> member)
    {
        Array<U> extracted;

        for (auto& item : array)
            extracted += member(item);

        return extracted;
    }
}


#define extract(container, member) detail::extract_(container, \
    std::function< typeof(typeof(container)::Type::element_type::member) (const typeof(container)::Type&)>( \
                   [&](const typeof(container)::Type& item){ return item->member; }))

这就是我要用来从数组中提取成员的算法。 Array<T>是我自产的数组类型,它处理出价。

如果您对宏过敏,对不起,但这会使用户代码很干净。

我想做的是,如果我有一个成员Array<Size> sizeArraydouble Array<Size>::Length,并且能够说auto lengths = extract(sizeArray, Length);,并且lengths的类型是Array<double>

我已经做过类似的事情

namespace detail
{
    template <typename T>
    Array<T> filter_(const Array<T>& array, std::function<bool(const T&)> condition)
    {
        Array<T> filtered;

        for (auto& item : array)
            if (condition(item)) filtered += item;

        return filtered;
    }
}


// this macro creates a capturing lambda, the item to check is called 'item'
#define filter(container, condition) detail::filter_(container, \
    std::function<bool(const typeof(container)::Type&)>( \
                   [&](const typeof(container)::Type& item){ return condition; }))

我可以做auto turnedOff = filter(objects, !item->IsTurnedOn);,并且确实可以很好地工作,但是它返回的是相同的类型,因此解决起来比较容易。

1 个答案:

答案 0 :(得分:4)

不要使用这些宏。请。为了上帝的爱。

现在我们已经解决了这个问题,这是一个可行的解决方案,它不涉及std::function的开销。

#include <iostream>
#include <vector>
#include <algorithm>

struct A
{
    int x;
    double y;
};

template <typename T, typename U>
auto extract(const std::vector<T>& vec, U T::* member)
{
    std::vector<U> result;
    result.reserve(vec.size());
    std::transform(
        std::begin(vec), std::end(vec), std::back_inserter(result),
        [member] (const T& val) { return val.*member; }
    );
    return result;
}

int main() {
    std::vector<A> as{{10, 3.14}, {42, 1.618}};
    auto result = extract(as, &A::x);
    for (auto x : result)
        std::cout << x << std::endl;
    return 0;
}

https://ideone.com/ewieLc