Stunt programming. Modern C++ is not about that.

Lambdas!

 

Yes. That divides modern C++ man,  from old C++ boys! We remember the factory pattern and we will use it here too.  Thus showing the unmistakable OO pedigree, too.

We will deliver the function template returning a lambda! Close to real stunt, but works And compiler has fewer problems disambiguating the instances

Looks much more in line with our “c++ ninja” status. Does it not? Very clever little stunt that is!

Testing

Also. The real modern C++ thinking shines through. Functional programming and the rest.  Function pointers are nicely (and obediently by the compiler) made. auto is used properly so there are no ugly pointers to instances of template functions. Or was it function templates?

But. Few little problems here too. First this pesky default argument issue. It seems the good old argument as “pointer to null” works the best as the default argument idiom. It seems it is far from modern C++. We try the “modern” solution on that line:
return [&](const T & new_ = defval_) { ... } 

But alas no can do:

error C2587: 'defval_': illegal use of local variable as default parameter

Oh? That is a bit of a surprise.  We quickly “Google out” for some advice but it seems nothing works. Time passes by.  Fine. Is this really a problem?

Well yes, it is. If we pass the pointer we need to guarantee it points into the meaningful value. This line is especially troublesome:

default_value = *new_;

We make two big assumptions here: first that de-referencing will produce a meaningful value of type T, and second that operator “=” exists and can take the right-hand side as we wish it to.

Hmm. Not entirely sure here. Should we try hard and pull some latest modern C++ tricks here? C++17 guides? Or some yet undiscovered nugget from the std lib.

And yes we also have noticed this solution does not work as we expect it to. It simply does not return the default value on the first call? Hm. Hm.

Working option Two

I am not an omnipotent C++ guru but let me jump in now and help our bright but somewhat unfortunate programmer and help provide a C++17 solution. With errors in logic removed too.

As before we will stay with the idea of function template returning a lambda. So what do we do to make this behave as we want it to?

On the first call, we execute the lambda and return it. Thus on the second and all the other calls, it will be used with a proper def value from the first call. You know: if we try simply  T new_ = defval_  that will not compile.

The elegant  (C++17) way around, is to use std::optional

(NOTE: lambda bellow requires T to be a movable type so if T is your class it better be movable)

Yes, this is a real modern C++17. std::optional<> and a such. And it works too.  So what could be possibly wrong with it?

The reality bites. It is very likely:

  • Your team/company is still on C++11, or is it C++03?
    • std::optional requires (at least) C++17
  • To your team, this code is pretty hard to understand
    • yes this is clever but definitely on the edge of “stunt”
  • To maintain or expand this code  authors presence is required
  • Here insert your favorite show stopper  …

What should we do? We should stop here and think. How would we actually implement this if we focus on the requirements instead of the latest features possible with the programming language we use. After all, if something is in there, in modern C++, that does not mean we have to use it.

Imperative (in case you forgot) is to solve the requirements. In a feasible manner.