@@ -220,26 +220,6 @@ void accepts_option(const Print::FormatterOption*);
220
220
// cluttering the global namespace. Could be removed if needed.
221
221
namespace Formatters {
222
222
223
-
224
- // TODO: Do we really need a FormatterOption base class? Without it,
225
- // options can be POD, not needing a constructor. With it, we can
226
- // prevent accidentally treating things as options which are not, but if
227
- // we already check a Formatter base class, we can also require that
228
- // Formatters do not define nonsensical addOption methods (even more,
229
- // without an explicit FormatterOption, Formatters can even use
230
- // non-class types as options if they want).
231
- // TODO: Where to define the "default formatter" for an option? Now, it
232
- // is our superclass, but it might just as well be defined with a using
233
- // directive directly here. Or perhaps it should be a method (this
234
- // might be problematic, since the DefaultFormatter type is incomplete
235
- // at this point). One completely different approach would be a
236
- // DefaultFormatterFor template, which gets specialized, but this
237
- // probably has the problem that once it is instantiated, you can no
238
- // longer add to it. Using specializations does allow defining a default
239
- // formatter for a type/option combination (allowing reuse of e.g. HEX
240
- // for custom types) or for just a type (allowing default formatting of
241
- // custom types).
242
-
243
223
class DefaultFormatter : public Print ::Formatter {
244
224
public:
245
225
// Common base class for our options
@@ -528,12 +508,61 @@ inline size_t Print::print( double n, int prec) { return print(n, FORMAT_
528
508
// accept the DefaultFormatter instance by-value, and a generic
529
509
// non-static printTo could be added that forwards all calls to the
530
510
// static versions. Doing this in DefaultFormatter instead of coding
531
- // this in Print/PrintHelper , leaves control over by-value/by-ref at the
511
+ // this in Print, leaves control over by-value/by-ref at the
532
512
// formatter author and probably gives the cleanest Formatter interface
533
- // (an alternative would to just have PrintHelper call a static printTo,
513
+ // (an alternative would to just have Print call a static printTo,
534
514
// in which case the formatter could still decide to accept the
535
515
// formatter instance by reference or by value).
536
516
//
517
+ // Limitation: Default formatters for a value type and/or option type
518
+ // are specified using overloads of the DefaultFormatterFor function.
519
+ // You can use templates to get wildcard overloads (e.g. specify a
520
+ // default formatter for all options passed to a specific type, or a
521
+ // default formatter for any type combined with a specific formatter).
522
+ //
523
+ // If both overloads exist, this might cause ambiguity. e.g. when you
524
+ // have a (FooT value, *) overload and a (*, BarOption) overload, doing
525
+ // print(FooT(), BarOption()) is ambiguous. Usually, this will also be
526
+ // invalid (the formatter belonging to BarOption will likely not know
527
+ // how to print a FooT anyway). There might be cases where it is not,
528
+ // but it is not clear which of the two to favor in this case. If
529
+ // needed, some kind of priority tag argument could later be added, with
530
+ // a fallback to the regular tag-less version). Also, even in the
531
+ // invalid case, the "ambiguous" error message is not so nice.
532
+ //
533
+ // Note that the current approach of using a formatter-specific
534
+ // superclass (e.g. DefaultFormatter::FormatterOption) between the
535
+ // actual option class and Print::FormatterOption already makes
536
+ // overloads that use it (and thus need parent class conversion) less
537
+ // specific than templated overloads (which match their arguments
538
+ // exactly). This resolves the ambiguity, but I'm not sure if this is
539
+ // the right resolution.
540
+
541
+ // Limitation: DefaultFormatterFor relies on argument-dependent-lookup
542
+ // (ADL) to work properly. Normally, when a function is called, only
543
+ // overloads defined up to where the function call is defined are
544
+ // considered (e.g. the call the DefaultFormatterFor in Print.h). In
545
+ // this case, we want to allow defining more overloads later. We can
546
+ // make this work because DefaultFormatterFor is only called from
547
+ // template functions, and for those ADL happens at template
548
+ // *instantiation time*, rather than *definition time*.
549
+ //
550
+ // ADL happens for all types in a namespace (including the root
551
+ // namespace). Notably, this means ADL happens for class types (options
552
+ // and custom value types), but not for native types (e.g. int does not
553
+ // live in a namespace). In practice, this means that replacing the
554
+ // default formatter for a native type (without any options) is not
555
+ // possible, since the reference to e.g. DefaultFormatterFor(int) is
556
+ // looked up at template definition time, not instantiation time.
557
+ //
558
+ // Two possible workarounds for this would be to add a wrapper class
559
+ // around values before passing them to DefaultFormatterFor, or adding
560
+ // an unused dummy argument that forces ADL. The latter is probably
561
+ // easiest, and if the dummy argument is called NoOption and is the
562
+ // second argument, that might actually be fairly easy to work with as
563
+ // well.
564
+ //
565
+ //
537
566
// Mail
538
567
//
539
568
// For adding options to formatters, I'm using the overloaded addition
@@ -556,3 +585,18 @@ inline size_t Print::print( double n, int prec) { return print(n, FORMAT_
556
585
// counts characters written for alignment?).
557
586
//
558
587
// Compatibility with C++ <= 11
588
+ //
589
+ // ADL needed for DefaultFormatterFor - no primitive types
590
+ //
591
+ // TODO: Suggest workaround for ADL/primitive types using wrapper type
592
+ // (not in mail). Probably requires priority tagging to try wrapped type
593
+ // before unwrapped type, or some kind of primitive/nonprimitive
594
+ // detection for SFINAE. Or add Dummy argument, to force (meaningless)
595
+ // ADL.
596
+ //
597
+ // TODO: See if accepts_formatter can be called in default template
598
+ // argument as well (these are filled in after deduction, right? We only
599
+ // depend on the type, not the argument value)?
600
+ //
601
+ // TODO: Use NoOption dummy argument to DefaultFormatterFor to force
602
+ // ADL?
0 commit comments