last day (15 days later) » 

18:50
4
Q: Finding the greatest number from three numbers

Robot_enthusiastThe user is prompted to enter three numbers. The function finds the largest number and outputs it to the user. What do you think of my overall program flow and style? #include <iostream> using namespace std; int maxNumber(int num1, int num2, int num3); //function prototype/declaration int m...

There is a possibility to write function that takes N arguments and gives the maximum. Though that would become scary very fast to those who don't like metaprogramming.
@Incomputable It's not scary. Just a base case and variadic templates. It's not really metaprogramming. Example: coliru.stacked-crooked.com/a/cd6137926330f8a4 .
@Justin, I meant no recursion version.
@Incomputable Easy
@Justin, you can't take them by value. Also you can't do any assignment. The problem is to be able to tell which is maximum only on comparable types, e.g. you don't know if they copy-default-move constructible or assignable at all. And all of the types should be taken by const reference.
18:50
@Incomputable It's not a good idea in general to take the parameters by reference because it becomes incredibly easy to get dangling references. Notice that even std::max with an initializer list does not. Other things: "no recursion version" is not needed at all. With literally any level of optimization, the exact same assembly is generated. My point was that it's not too much work to write an n-ary max function as long as you kind of understand how templates work; you don't need tons of metaprogramming ability. Creating a perfect function is usually unneeded.
@Justin, that's the reason why I am here, I want perfect things.
@Justin, iterative version will allow passing values of different types and will utter very troublesome error
std::common_type can be used for that
thats if I understand what {...} does correctly (constructs initializer list?)
@Incomputable It's easy enough to fix that; you could just do a static_assert in the function.
Yes that's what { ... } does.
@Justin the point I want to make is that there are many edge cases, and covering all of them is hard. I'm telling that from my experience on other template metaprogramming projects
@Justin it actually should be possible for types that are convertible, but std::initalizer_list won't work that way, due to taking addresses of them
18:55
I know there are edge cases. I've done a lot of template metaprogramming as well. But it's not hairy. It's simple enough to just write something and fix it when necessary.
IMO a max function should take its parameters by value because you avoid the hairy problems altogether and because it will mostly be only used for integral values, which should be trivially copyable/movable. And then you don't get bugs from max(myInteger, 2, 3)
there are legitimate cases to have for non copyable times. OK, lets agree that it is easy
Yes
Unfortunately, it's not really possible to design a completely robust max function for all reasonable use cases that doesn't require the user to be careful in order to avoid obscure bugs.
It is possible to make it so that max(myInteger, 2, 3) creates a compile error, though.
I guess my point is that it's easy if you don't worry about it being perfect
But if you want it to be perfect and have optimal performance, it's pretty difficult to get right.

last day (15 days later) »