重载 operator+ 以增加 boost::asio::ip 上的 IP 地址

Overload operator+ to increase IP addresses on boost::asio::ip

我想用来自 boost::asio 的 IP 地址进行数学运算。具体来说,我需要增加 and/or 在现有地址上添加给定的整数,以简化我正在编写的软件中的 IP 列表生成。

今天我使用自定义 类 来处理 IP 地址和网络,但我想移动到 boost::asio 这样我就可以依靠它们来正确地 check/validade 地址和网络属性。

我以这个工作代码为例(operator+ 部分除外):

using boost::asio::ip::make_address_v4;
using boost::asio::ip::address_v4;

auto add(const address_v4& address, std::size_t value = 1) {
    return make_address_v4(address.to_uint() + value);
}

// This is definitely wrong
auto operator+(std::size_t value, const address_v4& address) {
    return add(address, value);
}

int main() {
    auto ip1 = make_address_v4("192.168.1.1");
    fmt::print("IP address: {}\n", ip1.to_string());

    auto ip2 = make_address_v4(ip1.to_uint() + 1);
    fmt::print("IP address: {}\n", ip2.to_string());

    // Add function
    fmt::print("Added IP: {}\n", add(ip2, 8).to_string());
    fmt::print("Added IP: {}\n", add(ip2).to_string());

    // operator+
    fmt::print("Added IP: {}\n", (ip2 + 4).to_string());

    return 0;
}

add 函数按预期工作,但我不知道如何重载它,所以我可以做类似的事情:ip++ip + 4.

还有没有更好的方法来用 boost::asio::ip::address_v4 做数学?我总是得到 uint 的值并在那里做数学运算。

我考虑的另一个解决方案是继承 boost::asio::ip::address_v4 并创建自定义运算符,但我不知道这是否可行,如果可行,这似乎有点过分,甚至更糟,我不知道不知道这是不是一个好的做法,看起来不是。

谢谢。

从技术上讲,您需要超载:

// This is morally wrong
auto operator+(const address_v4& address, std::size_t value) {
    return add(address, value);
}

那是因为left-hand操作数是address_v4,不是size_t

Live demo

但是,请不要这样做。参见例如What are the basic rules and idioms for operator overloading?。这里的操作没有明确且无可争议的意义。有很多惊喜的空间。根据子网划分,递增地址可以使常规地址成为广播地址,甚至可以跨越不同的子网。

例如"10.10.9.254" + 0x01010101 == 11.11.10.255 毫无意义,"255.255.255.255" + 0x01010101 == "1.1.1.0" 更无意义。

你可能想要的是一个 subnet-aware enumerator/iterator 接口,如果你需要 non-sequential 遍历,甚至可以使用随机抽样。如果您将其抽象化,就好像 address_v4 是“只是一种算术类型”,那么您就在撒谎您的域信息。