我有一个功能 Foo
得到两个模板参数 L3HdrType
和 L4HdrType
.我收到一个数据包并解析它,然后需要调用该函数。我的代码目前看起来像:
ParsedPacket parsed_packet = parser.Parse(packet);
if (parsed_packet.ip_version() == IPv4 && parsed_packet.ip_proto() == TCP)
Foo(parsed_packet.L3Header<ipv4_hdr>(), parsed_packet.L4Header<tcp_hdr>());
if (parsed_packet.ip_version() == IPv6 && parsed_packet.ip_proto() == TCP)
Foo(parsed_packet.L3Header<ipv6_hdr>(), parsed_packet.L4Header<tcp_hdr>());
if (parsed_packet.ip_version() == IPv4 && parsed_packet.ip_proto() == UDP)
Foo(parsed_packet.L3Header<ipv4_hdr>(), parsed_packet.L4Header<udp_hdr>());
if (parsed_packet.ip_version() == IPv6 && parsed_packet.ip_proto() == UDP)
Foo(parsed_packet.L3Header<ipv6_hdr>(), parsed_packet.L4Header<udp_hdr>());
我的问题是,有没有办法减少这种代码重复?类似的东西:Foo<parsed_packet.GetL3HeaderType(), parsed_packet.GetL4HeaderType()>(...);
这显然不起作用,因为在编译时不知道给定数据包的 header 类型。重复的根源在于两个不同的 if 语句正在检查
IPv4
并将其映射到 ipv4_hdr
.如果我可以在代码中的一处指定 IPv4
映射到 ipv4_hdr
然后它会使代码随着选项的数量线性增长而不是指数增长,因为我可以以某种方式编写:if (parsed_packet.ip_version() == IPv4) {
using L3HeaderType = ipv4_hdr;
}
...
Foo<L3HeaderType, L4HeaderType>(...)
请注意,我的实际代码需要支持不止 4 种情况,因此实际代码比这里的示例要丑陋得多,因为 if 语句的数量随着 header 的数量呈指数增长。
最佳答案
如果继承和运行时多态性不是一个选项,您可以通过执行一些涉及 lambda 的杂技来解耦两个模板参数的推导:
template <typename T> struct foo {};
template <typename T> struct bar {};
// the function to be called
template <typename A, typename B>
void foobar( foo<A> f, bar<B> b) {}
// bind the first parameter
template <typename T>
auto make_foofoo (foo<T> f) {
return [f](auto bar){ foobar(f,bar); };
}
// select second type here
template <typename F>
void do_the_actual_call(F f, int y) {
if (y == 1) f(bar<int>{});
if (y == 2) f(bar<double>{});
}
int main() {
// the "conditions"
int x = 1;
int y = 2;
// select first type here
if (x == 1) {
auto foofoo = make_foofoo(foo<int>{});
do_the_actual_call(foofoo,y);
} else if (x == 2){
auto foofoo = make_foofoo(foo<double>{});
do_the_actual_call(foofoo,y);
}
}
它仍然是重复的代码,但它缩放为 x + y
不再是 x * y
.
关于c++ - 如何防止手动实例化所有模板类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64263462/