Using SFINAE to Control Overload Resolution

Tag Dispatching vs SFINAE

What is tag dispatching and how does it differ from SFINAE?

Illustration representing computer hardware

Tag dispatching is another technique in C++ for selecting function overloads based on properties of types. While it can often be used to solve similar problems as SFINAE, it works in a different way.

With tag dispatching, you define "tag" types that represent certain properties, and then you overload functions based on these tag types. The selection of the overload happens at the point where you determine which tag to pass to the function.

Here's an example that demonstrates tag dispatching:

#include <iostream>
#include <type_traits>

struct integral_tag {};
struct floating_point_tag {};

template <typename T>
constexpr auto get_tag() {
  if constexpr (std::is_integral_v<T>)
    return integral_tag{};
  else
    return floating_point_tag{};
}

void foo(integral_tag) {
  std::cout << "foo called with"
    " an integral type\n";
}

void foo(floating_point_tag) {
  std::cout << "foo called with a"
    " floating point type\n";
}

template <typename T>
void bar(T value) {
  foo(get_tag<T>());
}

int main() {
  bar(42);    // Calls foo(integral_tag)
  bar(3.14);  // Calls foo(floating_point_tag)
}
foo called with an integral type
foo called with a floating point type

Here, integral_tag and floating_point_tag are empty types that serve as "tags". The get_tag function returns an integral_tag if its type argument T is an integral type, and a floating_point_tag otherwise.

We then have two overloads of foo, one accepting an integral_tag and the other accepting a floating_point_tag.

In the bar function template, we call foo with the result of get_tag<T>(). So the selection of which foo overload to call happens at this point, based on the properties of T.

The key differences between tag dispatching and SFINAE are:

  1. With SFINAE, the selection happens during overload resolution. The compiler considers all overloads and discards those that would cause substitution failures. With tag dispatching, the selection happens at the point where you choose which tag to pass.
  2. SFINAE is a part of the template system and works with types and expressions. Tag dispatching is based on function overloading and works with values (the tags).
  3. SFINAE can be used to enable or disable function templates entirely. With tag dispatching, you typically have one main function template that dispatches to different implementations based on the tag.

Both techniques have their uses and can often be used to solve similar problems. Tag dispatching can be more readable in some cases, especially when the conditions for choosing an implementation are complex. However, SFINAE is more flexible and can be used in situations where tag dispatching would be cumbersome or impossible, such as enabling or disabling member functions of class templates.

This Question is from the Lesson:

Using SFINAE to Control Overload Resolution

Learn how SFINAE allows templates to remove themselves from overload resolution based on their arguments, and apply it in practical examples.

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Using SFINAE to Control Overload Resolution

Learn how SFINAE allows templates to remove themselves from overload resolution based on their arguments, and apply it in practical examples.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved