C++ Templates - Part 2: Basic syntax, specialization, tag dispatch and SFINAE

  Рет қаралды 25,105

oneproduct

oneproduct

Күн бұрын

Пікірлер
@enriquebenedicto9429
@enriquebenedicto9429 5 жыл бұрын
Excellent video. I liked how you walk through the evaluation process. And all with a smile.
@thisismuffinmuffin
@thisismuffinmuffin 5 жыл бұрын
The Best template tutorial!! What a pity Google's algorithm can't find out! You should do more.
@mateusz-czajkowski
@mateusz-czajkowski 4 жыл бұрын
agree. that's pity that he stopped recording c++ videos
@tubemelf
@tubemelf 3 жыл бұрын
Very good guidance! To expand a little more information and clarify the examples, forms 2 and 3 of SFINAE are overloads instead of template specializations. In case both full and partial specializations are needed for a function, MIXING both specializations and overloads (overloads to workaround function partial specialization not being allowed) won't work when the template function is used by means of forward declaration while all its definitions (specialized and overloaded) are in a different translation unit. (Unless all overloads are also forward declared, which defeats de purpose of having the single template function forward declared in the translation unit using it). True for any mixing of specializations and overloads including those overload forms of SFINAE. Reason being, the compiler will only try to find and match one of the specializations, oblivious to any overloads. Pre C++20 concepts, I've managed to overcome this only with tag dispatching.
@tomaspyth7017
@tomaspyth7017 6 жыл бұрын
With all this stuff still a smiling C++ Programmer!!! Respect👍👍👍
@GreatTutorialChannel
@GreatTutorialChannel Жыл бұрын
The best thing is not only to demonstrate a perfect flawless interactive presentation but make some errors, show them, solve them and explain what went wrong. When you do this the first time you get 90% errors before hitting the sweet spot that compiles.
@giladreich810
@giladreich810 6 жыл бұрын
Loved your videos about templates and how you enjoy explaining them with passion! I hope you'll make some more of these videos in the future! You're truly a great teacher. One thing I would like to suggest though, if you would make a separate channel just for programming videos, that would attract much more subscribers, as some of the viewers are not interested in other videos rather than learning about programming. You could also open Patreon account and add to your videos description for people who would like to support what you do here, as the content and the examples you provided are very valuable and helpful. Big like and thanks!
@unusualfashion
@unusualfashion 6 жыл бұрын
Thanks for the kind words. I've had other people suggest making another channel as well. I guess when I started I didn't think many people would be interested in this. I did it mostly to provide extra resources for some people at work, where I do some training. I haven't made any more videos in a while, but if I start up again I'll definitely keep that in mind. As for Patreon, I'll pass. :) I'm very much of the opinion that this kind of information should be provided freely by people who are happy to give it for free. I even disabled monetization on these videos so I don't get any KZbin revenue either.
@kim15742
@kim15742 7 жыл бұрын
Very good teacher!
@MrAlbinopapa
@MrAlbinopapa 5 жыл бұрын
For function overloads, you shouldn't create specializations, but instead just create the overload as if it were like fmax: template bool Equals( T lhs, T rhs ){ return lhs == rhs; } bool Equals( float lhs, float rhs ) {return true; } template specializations aren't suppose to participate in overload resolution. Just for passers by, instead of typing std::is_floating_point::value, you can also use the shortcut std::is_floating_point_v. For types, the shortcuts or aliases or typedefs end in _t and for values, the shortcuts end in _v. std::is_integral_v std::is_floating_point_v std::conditional_t std::enable_if_t I'm so glad C++17 added constexpr-if statements, now you can avoid tag dispatch and sfinae, template bool Equals( T lhs, T rhs ) { if constexpr( std::is_floating_point_v ) { return std::abs( rhs - lhs ) < static_cast(0.00001); } else { return lhs == rhs; } }
@unusualfashion
@unusualfashion 5 жыл бұрын
You're quite right about the overloading for specific types. I went into it with the template specialization approach to eventually lead towards the template for all floating point types. We're not quite using C++17 where I work just yet, but I'm looking forward to using constexpr-if when we make the switch. It certainly will be nice to remove some of the clunkier SFINAE syntax.
@MrAlbinopapa
@MrAlbinopapa 5 жыл бұрын
@@unusualfashion I appreciate the response, I understand why you used functions for the specialization, the comment wasn't so much for you, but for others. Nothing more frustrating than unexpected behavior down the road because they changed compilers or some flag where certain code no longer works. Honestly, I am surprised the specialization worked. I feel as though I have tried something similar in the past and the compiler wouldn't choose my specialization functions when I was first learning about templates. I enjoyed the explanations though, I did learn something. I had always wondered about the placement and syntax of enable_if in the standard library. I could use it in the return parameter part of a function, but I was never able to figure out the empty template parameter syntax.
@xudongsun
@xudongsun 3 жыл бұрын
May I know where and how you learned all these? amazing!
@jonathanmoore5619
@jonathanmoore5619 4 жыл бұрын
Echo that below. The best c++ vids on KZbin. Great way of teaching. Effortless... Seemingly.
@us5945
@us5945 2 жыл бұрын
27:19 I think std::enable_if_t::value>* will always be a void pointer, no matter what type of T is. Is my opinion right or wrong?
@unusualfashion
@unusualfashion 2 жыл бұрын
You're correct. std::enable_if takes two template arguments, the first is the boolean condition, and the second is the type that it should return, which is unrelated to the type of T that we're checking in the condition. By default, the second is void, so because it's not specified here it will return a void pointer as type, but you could specify it to be something else if you needed.
@readingchess
@readingchess 2 жыл бұрын
Did I see The Cherno walking around in the background?
@muckvix
@muckvix 7 жыл бұрын
Great tutorials, thx! One comment: it seems strange that the compiler would need help confirming that `conditional::type` is indeed a type. It seems evident from the syntax: if it's not a type, the `{}` right after it would be an error wouldn't it? And so couldn't the compiler simply assume it's a type from the syntax (and complain if it later discovers that it's actually not a type)? In fact, I tried to drop `typename` from `typename conditional::type{}` and MSVC 2017 compiled it without an error. Also, is there any reason to prefer the (newer) SFINAE over the (older) tag approach?
@unusualfashion
@unusualfashion 7 жыл бұрын
Good catch. You're quite right. One of the problems of doing these things without a script is that I'm more likely to make mistakes I suppose. :) That wasn't a good example of dependent types. In an argument list or return statement it's evident that it must be a value of a type. You only need to add typename when you are intending to name a type. A better minimal example might be (this pasted code is probably going to look awkward...): template struct Test { using DependentType = T; }; template struct Foo { static auto Bar() { return Test::DependentType{}; //don't need typename } using Something = typename Test::DependentType; //needs typename }; In Foo, the meaning of DependentType could depend on the value of T as there could be a template specialization of Test for T in which DependentType is something other than a type, such as a member or class variable.
@unusualfashion
@unusualfashion 7 жыл бұрын
I just noticed that second part of your question regarding SFINAE vs tag dispatch. Apparently the entry about SFINAE on cppreference ( en.cppreference.com/w/cpp/language/sfinae ) says: Alternatives Where applicable, tag dispatch, static_assert, and, if available, concepts, are usually preferred over direct use of SFINAE. I really can't say I have enough in-depth experience to know why those are preferred or to argue heavily in favor of one or the other when it comes to practical concerns. Personally, I prefer SFINAE over tag dispatch as I like how the constraints are more up front and visible in the function's signature and/or template types. Tag dispatch makes you dig into the function to see the constraint and then you have multiple functions that take arbitrary types like true_type and false_type without it being immediately obvious what the true_type and false_type mean. I don't currently work with a compiler that supports concepts, but when concepts are available to me perhaps I'll follow the guidance of the SFINAE page and use them instead, as they provide the same type of up front constraint declarations that I enjoy about SFINAE.
@kaustubhbansal6400
@kaustubhbansal6400 4 жыл бұрын
Really great tutorial. I liked your presentation style :)
@youcefsb4708
@youcefsb4708 3 жыл бұрын
Just like [*::type] can be simplified with [*_t], [*::value] can also be simplified with [*_v] in C++17.
@illya_ike
@illya_ike 7 жыл бұрын
Very good stuff: good examples, good explanation. Subscribed!
@antiHUMANDesigns
@antiHUMANDesigns 4 жыл бұрын
"People usually don't go out of their way to make void pointers"
@linus198062
@linus198062 4 жыл бұрын
Excellent video, thank you so much!
@ahmadalastal5303
@ahmadalastal5303 3 жыл бұрын
the first example of tag dispatch doesn't compile on my machine, I have VS2017 15.9 v14.16, any help ?
@unusualfashion
@unusualfashion 3 жыл бұрын
Try moving the definition of the first Equals below the definition for the other two that take true_type and false_type. They should have been first so that the generic Equals can see them properly.
@ahmadalastal5303
@ahmadalastal5303 3 жыл бұрын
@@unusualfashion amazing, now it is working
@interested_in_everything
@interested_in_everything 3 жыл бұрын
Can anyone explain why do we create a void pointer at 26:00
@Salxixons
@Salxixons 2 жыл бұрын
The idea is to get a signature that's like this during template substitution: bool equals(T lhs, T rhs, void* = nullptr); // which may look odd but equates to bool equals(T lhs, T rhs, void* some_val = nullptr); I'd rather have the void* type in enable_if_t directly rather than relying on default void eg: bool equals(T lhs, T rhs, enable_if_t::value,void*> = nullptr )
@TarunSingh-je9my
@TarunSingh-je9my 5 жыл бұрын
Nice explanation.I have doubt on iterator Why we need to provide specialization in iterator template void process(Iterator begin, Iterator end) { for (; itr != end; ++itr) { process(*itr); } } why i can't write void process(Iterator begin, Iterator end) { for (; itr != end; ++itr) { process(*itr); } } please explain
@unusualfashion
@unusualfashion 5 жыл бұрын
There can be many different types of iterators, so in your first example you're saying that you accept any type, and you'll call the type Iterator (and expecting for it to actually be or behave like an iterator). In the second one, it would only work for a class specifically called Iterator.
@jakobullmann7586
@jakobullmann7586 3 жыл бұрын
Is there any reason why this is not working for me? Visual Studio 2019 says: Error C2672 'Equals': no matching overloaded function found TestCpp template bool Equals(T lhs, T rhs) { return Equals(lhs, rhs, conditional_t{}); } template bool Equals(T lhs, T rhs, true_type) { cout
@jakobullmann7586
@jakobullmann7586 3 жыл бұрын
Actually I found out that if I put the definition of the dispatcher function last, rather than first, it compiles... Any idea why? Really strange...
@unusualfashion
@unusualfashion 3 жыл бұрын
Hm. When I copy your code into my editor it seems to work okay. Perhaps try moving the first equals beneath the other two. Otherwise if you have the line number the error was pointing too it could help. Mostly whether it's the call Equals(1.5f, 2.5f) or Equals(lhs, rhs, conditional_t{}) that it's referring to.
@jakobullmann7586
@jakobullmann7586 3 жыл бұрын
@@unusualfashion Hey, thanks a lot for replying! The error was shown in the Equals(T lhs, T rhs) body, where the tag dispatch happens. It does compile now, if I either move up the overloaded implementations or at least declare them prior to the Equals(T lhs, T rhs). I also tried this with G++/MinGW, the situation is the same. Just that G++ was kind enough to print a hint that the declaration should come before the call site...
@KeenlyJohnas
@KeenlyJohnas 3 жыл бұрын
Oh man, I know it is powerful - but I’ve seen the dark side of this - people starting hours and hours in spots of code to figure out what is going on - ending up making simple C decorators (tools for changing the sources) for such borderline situations - it is actually way simpler to read the code later on.
@LV-ei1ce
@LV-ei1ce 5 жыл бұрын
Amazing video !
@imteajsaimun4134
@imteajsaimun4134 2 жыл бұрын
Will c++20 concepts replace sfinae?
@unusualfashion
@unusualfashion 2 жыл бұрын
"if constexpr" from C++17 already removes a lot of the need for SFINAE, so no need to wait!
@burakcopur3841
@burakcopur3841 7 жыл бұрын
Can't we override operator== for two floats, rather than having a template specialization for this case?
@burakcopur3841
@burakcopur3841 7 жыл бұрын
Btw, you are explaining things nicely with pedagogical examples. I think you should do more videos on C++ topics.
@unusualfashion
@unusualfashion 7 жыл бұрын
You're actually not allowed to override operator== for two basic types. In Visual Studio with MSVC, if you try to write it, the red underline (of doom!) is accompanied by: nonmember operator requires a parameter with class or enum type. And if you try to compile it, the error is: error C2803: 'operator ==' must have at least one formal parameter of class type If you look at the documentation about operators at: en.cppreference.com/w/cpp/language/operators The description is: Customizes the C++ operators for operands of user-defined types. Emphasis on the user-defined. It would also be somewhat scary/confusing if you could have something like an operator+ for two integers which didn't return their sum. :)
@dnavas7719
@dnavas7719 6 жыл бұрын
Amazing video. Thanks.
@ВиккаДевятова
@ВиккаДевятова 2 жыл бұрын
Thank you.
@ИванБотяев-д2ы
@ИванБотяев-д2ы 5 жыл бұрын
Thank you very match. Its difficult to find lessons about templates on russian.
@RoamingAdhocrat
@RoamingAdhocrat 6 жыл бұрын
Fantastic - thanks so much!
@sebastianwilke626
@sebastianwilke626 3 жыл бұрын
Regarding what you showed at the end: "The behavior of a program that adds specializations for is_floating_point or is_floating_point_v (since C++17) is undefined." ( en.cppreference.com/w/cpp/types/is_floating_point )
@viraatchandra8498
@viraatchandra8498 6 жыл бұрын
Thank you so much!!
@Foo-i1v
@Foo-i1v 5 жыл бұрын
thank you so much
@MDM666666
@MDM666666 7 жыл бұрын
Dudeeeeeee, you have a seriously long neck. These are some good tutorials, though.
@unusualfashion
@unusualfashion 7 жыл бұрын
I am extremely amused that you pointed that out. I do have a seriously long neck, and it's particularly noticeable when I stand next to someone of similar height, because then you can see how low my shoulders are relative to that other person and just how much of my height comes from my neck.
@MrZyzbill
@MrZyzbill 5 жыл бұрын
"using namespace std" : Yucks
@amrtcpp6203
@amrtcpp6203 4 жыл бұрын
Thank you very match
C++ Templates - Part 3: Type Deduction
27:33
oneproduct
Рет қаралды 12 М.
黑天使被操控了#short #angel #clown
00:40
Super Beauty team
Рет қаралды 61 МЛН
How Strong Is Tape?
00:24
Stokes Twins
Рет қаралды 86 МЛН
Let's get comfortable with SFINAE (C++)
35:55
platis.solutions
Рет қаралды 8 М.
C++ Templates - Part 4 : Curiously Recurring Template Pattern
12:22
Python laid waste to my C++!
17:18
Sheafification of G
Рет қаралды 119 М.