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

5
我希望使用boost::asio对IP地址执行数学运算。具体来说,我需要在现有地址上增加给定的整数以便于在我编写的软件中生成IP列表。
目前我正在使用自定义类来处理IP地址和网络,但我希望转移到boost::asio上,以便我可以依靠它们正确地检查/验证地址和网络属性。
以下是示例代码(除了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 并创建自定义操作器,但我不知道这是否会起作用,即使它起作用,这似乎是过度设计或更糟的是,我不知道这是否是一个好的实践,它看起来并不是。
谢谢。

1
你可以交换 operator+ 函数的参数顺序来创建另一个 operator+ 重载,然后它就能正常工作了。auto operator+(const address_v4& address, std::size_t value) { return add(address, value); } - M. Galib Uludag
1个回答

1
要使其技术上运行,您需要超载:
// This is morally wrong
auto operator+(const address_v4& address, std::size_t value) {
    return add(address, value);
}

那是因为左操作数是address_v4,而不是size_t

在线演示

然而,请不要这样做。请参见例如什么是运算符重载的基本规则和习惯用法?。此处的操作没有明确和公认的含义。有很大的惊喜空间。根据子网划分,递增地址可能会将常规地址变成广播地址,甚至跨越到不同的子网。

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

您可能需要的是一个子网感知的枚举器/迭代器接口,如果您需要非顺序遍历,甚至可以带有随机抽样功能。如果您将此抽象为如果address_v4只是“一种算术类型”,那么您就在误导您的领域信息。

谢谢@sehe,但我无论如何都需要增加它。operator++就足够了,我理解你的推理,并且我正在考虑如何使其安全,例如在网络超出其边界时抛出异常。溢出检查也是一个好主意。重载+的想法是为了使代码更易于阅读,因为我将在for循环中执行+1以生成地址列表。 - Vinícius Ferrão
告诉我,是什么使++address可以,但increment(address)不行?“我会在for循环中使用+1来生成地址列表”的部分正是让我说,“你在这里可能想要一个子网感知的枚举/迭代器接口”。 - sehe
使用increment(address)也可以。因此,明确起见,您建议使用函数而忘记重载operator+(和operator ++)。 - Vinícius Ferrão
1
是的。 <padding/><padding/> - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接