I have a function `Foo` that gets two template args `L3HdrType` and `L4HdrType`. I receive a packet and parse it and then need to call the function. My code currently looks like:

```
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>());

```

My question is, is there any way to reduce this code duplication? Something along the lines of:

```
Foo<parsed_packet.GetL3HeaderType(), parsed_packet.GetL4HeaderType()>(...);

```

This clearly doesn't work since the given packet's header types aren't known at compile time.

The source of duplication is the fact that two different if-statements are checking `IPv4` and mapping it to `ipv4_hdr`. If I could in one place in the code specify that `IPv4` maps to `ipv4_hdr` then It would make the code grow linearly with the number of options and not exponentially since I could write somehow:

```
if (parsed_packet.ip_version() == IPv4) {
  using L3HeaderType = ipv4_hdr;
}
...
Foo<L3HeaderType, L4HeaderType>(...)

```

Note, my actual code needs to support more than just 4 cases so the code in reality is much uglier than the example here since the number of if-statements grows exponentially with the number of headers.