The class has two constructors: a template one (from a number) and a copy constructor. Write Value b(a) — and the build breaks. For a non-const a the compiler considers the template a better match than the copy constructor, and it tries to make a string out of a Value. The template needs to be told: "never accept Value".
Value b(a) does not call the copy constructor. The template constructor Value(U&&) wins the overload — and tries std::to_string on a Value, which breaks the build. Restrict the template (enable_if + is_same) so it ignores Value itself.
Value b(a) from a non-const lvalue must invoke the real copy constructor (the copy counter proves it)std::enable_if_t + std::decay_t/std::is_same_v) to exclude Value itselfconst Value keeps working tooU = Value& a better match for Value b(a) than const Value& of the copy constructor?std::decay_t<U> strip, and why compare the decayed type?For Value b(a) with non-const a, the template deduces U = Value& — a perfect match, while the copy constructor needs a const-qualification. That is why the template wins.
Add a default template parameter that SFINAEs the constructor away when std::decay_t<U> is Value.
Hit Submit (or ⌘/Ctrl + ↵) — test results will show up here.