5 ms·
A lot of time where I just write simple functions, I end up having to wrap them into objects because it is much more convenient when I want to do static polymor
by jcelerier 6y ago
A lot of time where I just write simple functions, I end up having to wrap them into objects because it is much more convenient when I want to do static polymorphism - sure, that function I'm writing now doesn't need state but then two days after I have to refactor because the next strategy I use does indeed require state.
e.g. :
template<typename F1, typename F2>
struct MyAlgorithm {
F1 f1; F2 f2;
void operator()(...) { ... f1(whatever); ... f2(whatever); }
};
you can't just pass functions to F1 or F2, they have to be objects.
I remember this happening to me at least half a dozen times so far so now I just don't waste time and write them as structs with an operator() directly if it's anything that is meant to be used as a callback somewhere.
See also item 46 on Scott Meyers' "Programming with the STL" which points out a few other issues which can arise from using functions.
- enriquto 6y ago> struct MyAlgorithm This is a particularly bad name for your situation. An algorithm is not an object. Why not "my_state"?
- jcelerier 6y ago> Why not "my_state"? because it's a HN post and not real code ? And it contains the code of the algorithm, in the operator()... function. So my_state would only tell half the story. When I use it, what do you think makes more sense : GameExecutionAlgorithm<TensorflowGameStrategy> game_algo; next_positions = game_algo(...); or GameExecutionState<TensorflowGameStrategy> game_state; next_positions = game_state(...); > An algorithm is not an object. That is however completely conflating two different things. By that line of reasoning you couldn't write algorithms in e.g. Java or Smalltalk because there everything is an object and "an algorithm is not an object" => "there are no algorithms in Java / Smalltalk". Objects are just a syntax construct without attached meaning (or, if you did attach one at some point by reading some 1980 OOP book, please detach from it as that only causes confusion).
- enriquto 6y ago>When I use it, what do you think makes more sense : > (...) None of your examples make any sense to me. Why not name it simply "game"?
- msclrhd 6y agoWhat about something like "in_order_traversal", which is an algorithm and you need to keep track of the traversed stack. You could either write it with functions in which case you would need to pass the stack as a parameter and have a constructor/initial state version of the function that passes the stack to the main function, or have a functor/function class that keeps the stack internally.
- jcelerier 6y agolikely "game" would be something that would be about the whole game, including graphics, sounds, etc.
- bigbizisverywyz 6y agoSo there are 3 hard problems in programming. 1. Naming things, and .. I forget what the other one is.
- amw-zero 6y agoThis is a limitation of C++, not functions.
- jcelerier 6y agoyeah... but that's a C++ article, written by someone who contributes to the C++ standard... the context seems unambiguous
- steerablesafe 6y ago> you can't just pass functions to F1 or F2, they have to be objects. Why? https://godbolt.org/z/2kJsT9 https://godbolt.org/z/2kJsT9
- jkcxn 6y agoI'm new to C++, what are lines 11-12 for? I see that it doesn't compile without it. It doesn't seem to be the new 'arrow return type' syntax because there's no auto keyword. Edit: I found it - it's a 'template deduction guide' https://stackoverflow.com/questions/40951697/what-are-template-deduction-guides-and-when-should-we-use-them https://stackoverflow.com/questions/40951697/what-are-templa...
- gpderetta 6y agoYes, the functionality was added in C++17, it is quite convenient, before you had to write boilerplate make_X 'constructor' functions. In C++20 this specific deduction guide is no longer required as it is implicitly generated for template aggregates, so even less boilerplate.
- jcelerier 6y agothat only works if you are in a context where you can deduce the type from ctor arguments, which is definitely not all cases (for instance, storing as a member and initializing in a ctor, etc...)
- gpderetta 6y agoYou can then specify the function pointer type, although mildly inconvenient. If you want to use lambdas though, then yes, you are out of luck as their type is unnameable.
- jcelerier 6y agobut that fails as soon as you have a case where you want to pass an algorithm implementation that does have state. That was my point - whenever I assumed that I would not have state... well I ended up needing to refactor everything because I ended up needing to add a new strategy that did require some state later. In the context of C++, struct / class types are more generic that function pointers and there's no real shortcut around this - that's how the language is specified.
- HarHarVeryFunny 6y agoIt's a trade off - if you want dispatch efficiency then use functions, if you want flexibility use std::function and you can store functions, functors or lambdas.