From 79fcf2400f08ce3b282d4547477aedbd6580a776 Mon Sep 17 00:00:00 2001 From: Mikhail Ostashchenko Date: Fri, 25 Aug 2023 20:38:41 +0200 Subject: [PATCH] SFINAE fix (C++) (#4390) When you try to use these function templates, there can be ambiguity issues. If you call foo with an arithmetic type, both template overloads will be considered valid, and the compiler won't know which one to choose. You can use specialization or tag dispatching to properly handle different cases. --- .../cpp/content/111-templates/103-finae.md | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/data/roadmaps/cpp/content/111-templates/103-finae.md b/src/data/roadmaps/cpp/content/111-templates/103-finae.md index be4e57461..6d23f9647 100644 --- a/src/data/roadmaps/cpp/content/111-templates/103-finae.md +++ b/src/data/roadmaps/cpp/content/111-templates/103-finae.md @@ -12,14 +12,23 @@ Here's an example that demonstrates SFINAE in action: #include #include -template ::value>> +template +struct foo_impl { + void operator()(T t) { + std::cout << "Called when T is not arithmetic" << std::endl; + } +}; + +template +struct foo_impl::value>> { + void operator()(T t) { + std::cout << "Called when T is arithmetic" << std::endl; + } +}; + +template void foo(T t) { - std::cout << "Called when T is arithmetic" << std::endl; -} - -template ::value>> -void foo(T t) { - std::cout << "Called when T is not arithmetic" << std::endl; + foo_impl()(t); } int main() { @@ -31,6 +40,6 @@ int main() { } ``` -In this example, we define two `foo` function template specializations. The first one is enabled when `T` is an arithmetic type, while the second one is enabled when `T` is not an arithmetic type. The `std::enable_if_t` inside the template parameter list allows us to control which specialization is valid for a given type of `T`. +In this example, we define two `foo_impl` functions are specialized based on the boolean value of `std::is_arithmetic`. The first one is enabled when `T` is an arithmetic type, while the second one is enabled when `T` is not an arithmetic type. The `foo` function then calls the appropriate `foo_impl` specialization based on the result of the type trait. -When calling `foo(a)` with an integer, the first specialization is selected, and when calling `foo(s)` with a string, the second specialization is selected. If there is no valid specialization, the code would fail to compile. \ No newline at end of file +When calling `foo(a)` with an integer, the first specialization is selected, and when calling `foo(s)` with a string, the second specialization is selected. If there is no valid specialization, the code would fail to compile.