1

In the following code sample:

template<typename T>
struct Foo
{
    template<typename U = T>
    typename std::enable_if<std::is_same<U, int>::value>::type
    MyFunction()
    {
        std::cout << "T is int." << std::endl;
    }

    template<typename U = T>
    typename std::enable_if<std::is_same<U, float>::value>::type
    MyFunction()
    {
        std::cout << "T is not int." << std::endl;
    }
};

What is the point of the template<typename U = T> part?

When we create an instance of Foo, with a type int, the T will be int. Now we have another type U, which is equal to T. Therefore, it is int as well. (The same applies for any other provided type.) It looks like a redundant part of code, because T=U=int. But, if I remove the template<typename U = T>, the code will not compile (U was replaced with T in is_same in that case).

Can somebody in detail explain what it going on here in compile time?

I'm not interested in answers like "That's SFINAE, that's how SFINAE works". Answers like that are useless.

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • 1
    TL;DR of the dupe: Without `template` `MyFunction()` is not a template so you can't use SFINAE. Even though it is a member of a template, it has to be a template itself to use SFINAE. – NathanOliver Aug 19 '19 at 15:46
  • 2
    As you most likely know, "SFINAE" = "Substitution Failure Is Not An Error". Substitution is what happens during template argument deduction (the compiler tries to substitute deduced types into the signature, SFINAE means "if that leads to an invalid signature, just move on"). If your function is not a template, there is no deduction, hence no substitution, hence no SFINAE. – Max Langhof Aug 19 '19 at 15:46
  • @NathanOliver, @Max Langhof, thanks for the comment, but some things are still unknown here. If I simply write this `template MyFunction()`, the code is not valid. But, the method is a template. So, why exactly ``?? –  Aug 19 '19 at 15:56
  • @InyangaInyanga You can't use `T` because the class template uses `T`. How would you tell which `T` you wanted? – NathanOliver Aug 19 '19 at 15:58
  • @NathanOliver, I'm afraid I don't understand what are you trying to say. The `Foo` accepts only one type. What do you mean by: which `T` I wanted? –  Aug 19 '19 at 16:04
  • 1
    You can't do `template MyFunction()` because the class is declared as `template struct Foo`. That would be reusing `T` and you can't do that. So you use `template` so that you have a template and `U` does not need to be deduced. – NathanOliver Aug 19 '19 at 16:05
  • @NathanOliver, feel free to call me stupid, but I still don't get it. Are you able to explain **in detail** what is compiler doing when I instantiate the `Foo` with `int` and what when I instantiate it with `float`? I can also ask a separate question if it suites you better. –  Aug 19 '19 at 16:14
  • Follow the link in the banner. The question has 5 answers. – L. F. Aug 19 '19 at 16:38
  • @L.F. It does not explain what I'm asking. Read the question again. –  Aug 19 '19 at 16:42
  • @InyangaInyanga Yes, it does. It explains exactly what `template ` does here. Read that question again. – L. F. Aug 19 '19 at 16:43
  • @L.F, no it does not say what is going on there in compile time when I pass `int` vs. `float`, vs. `whatever`. That's the whole point of this question. If you cannot answer it, that's fine. Maybe someone else can. –  Aug 19 '19 at 16:47
  • @InyangaInyanga I won't try to argue with you why this question is a dupe of that question anymore, but please note that no one can answer a closed question :) – L. F. Aug 19 '19 at 16:49
  • they are just saying the the typename U is equal to typename T as a default type, so if the class is using int for T, the U will also be int unless you say otherwise – daniel Aug 19 '19 at 16:52

0 Answers0