Tag Dispatching vs SFINAE

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

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.

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.

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Using SFINAE with Multiple Template Parameters
How can I apply SFINAE when my template has multiple parameters?
Applying SFINAE to Non-Type Template Parameters
Can I use SFINAE with non-type template parameters, like integers?
Interaction between SFINAE and Overloaded Functions
How does SFINAE interact with normal overloaded functions?
SFINAE vs Concepts: Which should I use?
I've heard that C++20 Concepts can replace SFINAE. Should I still learn SFINAE?
Using SFINAE to Check for Member Types
Can I use SFINAE to check if a type has a specific member type?
Interaction between SFINAE and Default Template Arguments
How does SFINAE work with default template arguments?
Applying SFINAE to Variadic Templates
Can SFINAE be used with variadic templates?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant