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

Option Three

Contents

Ok. Sobering time. Cold head.  May I remind you (of course) we all know very well about the good old Function Object aka “Functor”. So let’s do a proverbial step back and use what we already know. Bellow is the very bland looking very traditional C++ solution.  I am not sure but perhaps even C++98 compiler could produce a decent byte code from this?

/*
No stunts. A plain old function object. 
Simple usable and working
*/
template<typename T>
class holder {
 // mutable members of const class instances are modifiable
  mutable T default_value_{};
public:
 holder(const T & defval_) : default_value_(defval_) {
 };

const T & operator () () const noexcept {
   return default_value_;
}
/*
The operator declaration bellow
allows for const isntances to be used 
through the operator bellow 
    const holder<REAL> width{ 10 };
    width(1024) ; // OK
*/
const volatile T & operator () 
  (const T & new_ ) const volatile noexcept 
{
 if (new_ != default_value_)
   default_value_ = new_;
 return default_value_;
}
};

Testing begins here

 namespace {
   using namespace Gdiplus; // test the const behaviour
     const holder<REAL> width{ 10 };
     holder<SmoothingMode> 
         smoothnes{ SmoothingMode::SmoothingModeAntiAlias };
     holder<LineCap> 
         linecap{ LineCap::LineCapRound };

   inline void usage() {
    auto width_ = width( 1024 );
    const auto w1_ = width();
    auto w2_ = width();
           assert(width_ == 1024);
           assert(w2_ == w1_ == width_);
    auto lc_ = linecap();
    auto sm_ = smoothnes();
   }
}

This is one sober solution indeed. And working too. Usage seems simple and with no surprises.

Also the default argument issue is solved the C++ way. Modern or not. By using () operator overload, on the class.

What also is delivered is correct behavior in case of const required.  Code above is documented. And easy to maintain, expand or do whatever might be required down the line.