@@ -161,7 +161,7 @@ class Print
161
161
detail::enable_if_base_of<Print::FormatterOption, TOption>* = nullptr
162
162
>
163
163
_always_inline size_t printMultiple (const T &arg, const TFormatter &formatter, const TOption &option, const Ts &...args) {
164
- return printMultiple (arg, formatter + option, args...);
164
+ return printMultiple (arg, applyOption ( formatter, option) , args...);
165
165
}
166
166
167
167
// A value and an option is specified: Look up the default formatter
@@ -219,6 +219,16 @@ class Print
219
219
void accepts_formatter (const Print::Formatter*);
220
220
void accepts_option (const Print::FormatterOption*);
221
221
222
+ // Global function to apply an option on a given formatter. This version
223
+ // just calls the applyOption method on the formatter, if it exists. By
224
+ // going through this global function, it is possible to add overloads
225
+ // to add options for an existing formatter.
226
+ template <typename TFormatter, typename TOption>
227
+ _always_inline inline auto applyOption (const TFormatter& formatter, const TOption& option)
228
+ -> decltype(formatter.applyOption(option)) {
229
+ return formatter.applyOption (option);
230
+ }
231
+
222
232
// Namespace for more advanced custom formatter stuff, to prevent
223
233
// cluttering the global namespace. Could be removed if needed.
224
234
namespace Formatters {
@@ -280,23 +290,23 @@ class DefaultFormatter : public Print::Formatter {
280
290
constexpr FormatOptionBase (uint8_t value) : value(value) { }
281
291
uint8_t value;
282
292
};
283
- constexpr DefaultFormatter operator + (FormatOptionBase o) {
293
+ constexpr DefaultFormatter applyOption (FormatOptionBase o) {
284
294
return {o.value , this ->min_width , this ->precision };
285
295
}
286
296
287
297
struct FormatOptionPrecision : FormatterOption {
288
298
constexpr FormatOptionPrecision (uint8_t value) : value(value) { }
289
299
uint8_t value;
290
300
};
291
- constexpr DefaultFormatter operator + (FormatOptionPrecision o) {
301
+ constexpr DefaultFormatter applyOption (FormatOptionPrecision o) {
292
302
return {this ->base , this ->min_width , o.value };
293
303
}
294
304
295
305
struct FormatOptionMinWidth : FormatterOption {
296
306
constexpr FormatOptionMinWidth (uint8_t value) : value(value) { }
297
307
uint8_t value;
298
308
};
299
- constexpr DefaultFormatter operator + (FormatOptionMinWidth o) {
309
+ constexpr DefaultFormatter applyOption (FormatOptionMinWidth o) {
300
310
return {this ->base , o.value , this ->precision };
301
311
}
302
312
@@ -372,7 +382,7 @@ class OptionList : public Print::FormatterOption {
372
382
typename TOption,
373
383
detail::enable_if_base_of<Print::FormatterOption, TOption>* = nullptr
374
384
>
375
- constexpr auto operator +(const TOption& option) const
385
+ constexpr auto operator +(const TOption& option) const
376
386
-> OptionList<TOption, decltype(this ->tail + option)>
377
387
{
378
388
return {this ->head , this ->tail + option};
@@ -406,7 +416,7 @@ struct OptionList<THead, void> : public Print::FormatterOption {
406
416
typename TOption,
407
417
detail::enable_if_base_of<Print::FormatterOption, TOption>* = nullptr
408
418
>
409
- constexpr auto operator +(const TOption& option) const
419
+ constexpr auto operator +(const TOption& option) const
410
420
-> OptionList<THead, OptionList<TOption, void >>
411
421
{
412
422
return {this ->head , option};
@@ -417,7 +427,7 @@ struct OptionList<THead, void> : public Print::FormatterOption {
417
427
// Apply an option list by adding it to a formatter (e.g. by passing it
418
428
// to print())
419
429
template <typename TFormatter, typename THead, typename TTail>
420
- constexpr auto operator + (const TFormatter& formatter, const OptionList<THead, TTail>& list)
430
+ constexpr auto applyOption (const TFormatter& formatter, const OptionList<THead, TTail>& list)
421
431
-> decltype(list.addToFormatter(formatter))
422
432
{
423
433
return list.addToFormatter (formatter);
@@ -580,7 +590,12 @@ inline size_t Print::print( double n, int prec) { return print(n, FORMAT_
580
590
// existing formatter, without having to modify the formatter. If we
581
591
// prefer a normal method/function, the same could probably be obtained
582
592
// using a global overloaded addOption function (with a template version
583
- // that defers to an addOption method if it exists).
593
+ // that defers to an addOption method if it exists). After writing this,
594
+ // I realized that a method/function name is probably gives more
595
+ // readable errors (e.g. "no such function applyOption(DefaultFormatter,
596
+ // SomeOption)", rather than "no such operator
597
+ // operator+(DefaultFormatter, SomeOption)"), so we should probably do
598
+ // that.
584
599
//
585
600
// Formatters and options are currently passed around as const
586
601
// references, meaning that their printTo methods and addition operators
@@ -596,15 +611,9 @@ inline size_t Print::print( double n, int prec) { return print(n, FORMAT_
596
611
//
597
612
// ADL needed for DefaultFormatterFor - no primitive types
598
613
//
599
- // TODO: Suggest workaround for ADL/primitive types using wrapper type
600
- // (not in mail). Probably requires priority tagging to try wrapped type
601
- // before unwrapped type, or some kind of primitive/nonprimitive
602
- // detection for SFINAE. Or add Dummy argument, to force (meaningless)
603
- // ADL.
604
- //
605
- // TODO: See if accepts_formatter can be called in default template
606
- // argument as well (these are filled in after deduction, right? We only
607
- // depend on the type, not the argument value)?
614
+ // Compare with Printable
608
615
//
609
616
// TODO: Use NoOption dummy argument to DefaultFormatterFor to force
610
617
// ADL?
618
+ //
619
+ // TODO: Convert operator+ to applyOption?
0 commit comments