Interaction between SFINAE and Default Template Arguments

How does SFINAE work with default template arguments?

SFINAE can be used in conjunction with default template arguments to provide different default behaviors based on the properties of the template arguments. Consider this example:

#include <iostream>
#include <string>
#include <type_traits>

using std::enable_if_t, std::is_integral_v;

template <typename T, typename enable_if_t<
  is_integral_v<T>, int>* = nullptr>
void print(T value, int base = 10) {
  std::cout << "Integral value: "
    << std::to_string(value)
    << " (base " << base << ")\n";
}

template <typename T, typename enable_if_t<
  !is_integral_v<T>, int>* = nullptr>
void print(T value, int precision = 2) {
  std::cout << "Non-integral value: "
    << std::to_string(value)
    << " (precision " << precision << ")\n";
}

int main() {
  // Uses first template, base defaults to 10
  print(42);
  // Uses first template, base is 2
  print(42, 2);

  // Uses second template, precision defaults to 2
  print(3.14);
  // Uses second template, precision is 4
  print(3.14, 4);
}
Integral value: 42 (base 10)
Integral value: 42 (base 2)
Non-integral value: 3.140000 (precision 2)
Non-integral value: 3.140000 (precision 4)

Here, we have two print function templates. The first one is enabled if T is an integral type, and it has a default argument base for the output base. The second one is enabled if T is not an integral type, and it has a default argument precision for the output precision.

When we call print(42), the first template is selected because int is an integral type. The base parameter defaults to 10. When we call print(42, 2), the first template is still selected, but we override the default base with 2.

Similarly, when we call print(3.14), the second template is selected because double is not an integral type. The precision parameter defaults to 2. When we call print(3.14, 4), the second template is still selected, but we override the default precision with 4.

This demonstrates how SFINAE can be used to provide different default behaviors for a function based on the properties of its template arguments. This can lead to more intuitive and user-friendly interfaces, as the appropriate defaults are selected automatically based on the types being used.

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?
Applying SFINAE to Variadic Templates
Can SFINAE be used with variadic templates?
Tag Dispatching vs SFINAE
What is tag dispatching and how does it differ from SFINAE?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant