The original idea here was that we would take the parameter pack and store it as both a tuple and a vector. To put things in a vector the items had to share a common base, so I made this format_adapter_base. Then there were 2 implementations. One implementation that would be used for types where the format method would invoke a member function on the type itself, and another where a global formatter would be used.
But we can make this simpler though. The only thing we need to store is just the value itself, and we can defer the knowledge of what kind of formatter it uses until we actually go to format it, and we can have the final selection just delegate to a global template function that is properly specialized. This has the advantage of making the template glue much simpler, but also allowing us a convenient syntax to define new formatters via a macro. A few existing formatters are converted to this new syntax as an example. The rest can be done in a followup, for now I just want to see if the approach is ok.
Eventually I'd like to get the point where the adapters are composable, so you can say like align(pad(Value, 7), Left, 3) but part of that means simplifying the underlying glue so that there's fewer moving parts.
Not sure this benefits much from being a macro, does it?
Calls to these functions look like they're ADL compatible, so there's no need to put them in the llvm namespace - they can go in whatever namespace the Type is in, probably? (doesn't matter too much in the LLVM project - we don't need to protect the llvm namespace, etc, but is perhaps a more generic extensibility mechanism than users having to write function definitions in the library's namespace)