带运算符的std :: array的C ++ 11类型别名

问题描述 投票:2回答:2

我有一个c ++ 11类型的别名:

using coord = std::array<double, 3>;

我可以为coord定义运算符+吗?怎么样?我希望能够做到:

coord a, b, c;
a = {1.1, 2.0, 0};
b = {0, -1, 3.5};
c = a + b; // c = {1.1, 1.0, 3.5}
c++ c++11 typedef
2个回答
6
投票

我不建议为STL类型或任何不在您控制范围内的类型定义新运算符。

我建议改为创建自己的类型:

struct coord {
    // reimplement operator[], fill, size, etc.

    friend constexpr auto operator+ (coord const& lhs, coord const& rhs) noexcept -> coord {
        // ...
    }

private:
    std::array<double, 3> _coord;
};

或者您也可以使用qazxsw poi中已定义的运算符和成员函数来快捷方式:

std::array

注意:如果你想支持结构化绑定并提供类似访问你的struct coord : private std::array<double, 3> { constexpr coord(double a, double b, double c) noexcept : array{a, b, c} {} using array::operator[]; using array::begin; using array::end; using array::fill; // other operators... friend constexpr auto operator+ (coord const& lhs, coord const& rhs) noexcept -> coord { // ... } }; 类的元组,那么你必须为coord添加重载并专门化getstd::tuple_size

std::tuple_element

当您切换C ++ 17时,此代码将允许这种代码:

namespace std {
    template<size_t n>
    tuple_element<n, ::coord> {
        using type = double;
    };


    tuple_size<::coord> : integral_constant<size_t, 3> {};
}

template<std::size_t n>
constexpr auto get(coord const& c) noexcept -> double const& {
    return c[n]
}

template<std::size_t n>
constexpr auto get(coord& c) noexcept -> double& {
    return c[n];
}

template<std::size_t n>
constexpr auto get(coord&& c) noexcept -> double&& {
    return std::move(c[n]);
}

template<std::size_t n>
constexpr auto get(coord const&& c) noexcept -> double const&& {
    return std::move(c[n]);
}

1
投票

我想补充为什么你不应该为auto my_coord = coord{1.0, 2.0, 3.0}; auto [x, y, z] = my_coord; 添加operator+。或者,更一般地说,为什么你应该只将操作符(或者更确切地说是自由函数)添加到它们所操作类型的命名空间(在std::array的情况下是禁止的)。

首先,你不能把运算符放在命名空间std中,然后在命名空间A(没有B)中正确使用它:

using namespace A;

namespace A { using coord = std::array<double, 3>; // Putting this in the global namespace doesn't help. coord operator+(const coord& right, const coord& left) { return coord { right[0] + left[0], right[1] + left[1], right[2] + left[2] }; } } auto foo() { A::coord x, y; return x + y; // doesn't see the operator }

放置运算符的唯一地方是全局命名空间。如果这不会让你感到不舒服,这就是为什么它应该:名称查找规则将很快打破你的脖子。

如果我们想要编写一个使用https://godbolt.org/z/XUR_NX的模板怎么办?它应该工作正常,对吗?

operator+

template<class ... T> auto add(T ... t) { return (t + ...); }

是的,它的作品!好吧,直到有人添加任何https://godbolt.org/z/Ox8_r5更接近模板:

operator+

namespace A { struct X{}; void operator+(X, X); template<class ... T> auto add(T ... t) { return (t + ...); // won't find the correct operator+ for T=coord } }

名称查找在https://godbolt.org/z/ctcfxr处停止。由于您的正确值(对于operator+)不在std::arraynamespace std所在的位置),因此ADL(参数相关查找)无法找到它。那时你没有选择。

© www.soinside.com 2019 - 2024. All rights reserved.