重载 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
。
但是,请不要这样做。参见例如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
是“只是一种算术类型”,那么您就在撒谎您的域信息。
我想用来自 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
。
但是,请不要这样做。参见例如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
是“只是一种算术类型”,那么您就在撒谎您的域信息。