2

我认为==for的默认重载valarray不是很方便。默认情况下x==y(对于两个 valarrays x 和 y)返回 a valarray<bool>truei第 th 条目上带有 if x[i]==y[i]。相反,我需要一个bool,它告诉我两者是否valarray<double>包含相同的元素。我知道我可以用一个循环来做到这一点,但是每次都必须做这个循环并不方便。这里最好的解决方法是什么?有没有办法让我定义自己的重载==(以及!=,,<等等)?

4

4 回答 4

3

“不太方便”?这种行为正是valarray.

推翻它完全是弄巧成拙。

如果您不喜欢它,只需使用 avector代替。

于 2015-06-29T21:26:23.127 回答
1

不要覆盖默认operator==使用,例如:

bool isEqual( const std::valarray< bool >& aResult )
{
    bool equals = true;
    for ( auto item : aResult )
    {
        equals &= item;
    }
    return equals;
}

然后使用它:

std::valarray< int > x;
std::valarray< int > y;

bool equals = isEqual( x == y );
于 2015-06-29T21:33:53.983 回答
1

我同意其他人不超越==运营商。原因是这些运算符是使用valarray. 如果您不需要逐元素运算符,请不要使用valarray. 此外,您可能在某些时候需要操作员的原始版本,那么您为什么要把它扔掉呢?

我喜欢 pig 的解决方案,但如果效率是一个主要问题,我会像这样修改它:

#include <utility>
#include <valarray>

template <typename T>
bool isEqual( const std::valarray<T>& x,const std::valarray<T>& b) {
    bool equals = true;

    for (auto it = std::make_pair(std::begin(x), std::begin(b));it.first != std::end(x);++it.first,++it.second) {
        equals &= ((*it.first) == (*it.second));
        if (!equals) break;
    }
    return equals;
}

并像这样使用它

valarray<T> x,y;
bool b = isEqual(x,y);

通过不使用内置的,==不必比较 valarrays 中的所有元素。

PS:

+只是一个例子。我也想要-、*等。此外,我知道 valarray 有这些运算符的人为版本,它们比简单的实现更有效(我认为他们使用代理类将中间结果存储在 x + y + z 这样的表达式中,然后一起评估整个表达式)。我想利用这些。

实际上,这很有趣,我以前不知道。结论应该是:不要覆盖这些运算符,否则您将无法利用它们的巧妙实现。

于 2015-06-30T18:03:53.303 回答
0

如果您决定为商品“覆盖” std::valarray(而不是像user463035818 的答案operator==那样编写命名函数),您可以编写一个自定义“适配器”类:

template<typename T>
class CustomValArray : public std::valarray<T> {
public:
    typedef std::valarray<T> base;
    // We need to re-implement any non-default constructors we want to use:
    CustomValArray(std::initializer_list<T> init) : base(init) {}
};

/// Accumulation (single bool) comparison 
template<typename T>
bool operator==(const CustomValArray<T> &lhs, const CustomValArray<T> &rhs) {
    return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
}

如果您还希望能够使用原始operator==for std::valarray,您可以通过编写一个命名函数来实现:

/// Element-wise comparison
template<typename T>
auto elementWiseEqual(const CustomValArray<T> &lhs, const CustomValArray<T> &rhs)  {
    // We delegate to operator==(const std::valarray<T> &, const std::valarray<T> &)
    typedef std::valarray<T> base;
    return dynamic_cast<const base &>(lhs) == dynamic_cast<const base &>(rhs);
}

注意:上面的代码片段使用了 C++14 的自动返回类型推导。如果您使用的是 C++11,则应该-> decltype(std::valarray<T>() == std::valarray<T>())在声明符的末尾添加类似的内容。

在这里试试。

如果您选择这样做,直接从 继承std::valarray,请注意从 STL 类继承可能存在的风险


作为替代方案,您可以拥有一个带有std::valarray<T>私有成员的包装类,并手动将您想要使用的任何成员函数委托给std::valarray.

于 2019-04-11T14:40:35.723 回答