<div dir="ltr">To elaborate about member function vs format provider, decoupling types from the way they're formatted seems like a good design practice in general.  For example, you might want to add support for formatting a class which you don't have the code to.  Sure, you can do it one way whenever possible and another way whenever it's not possible, but since tight coupling leads to more fragile code as a general rule, it seems better to prefer the loose coupling whenever possible.<div><br></div><div>On the other hand, there are certain times when you *must* use a member-based formatter.  For example, when something already has a formatter defined for it (either via member syntax or format_provider specialization) and you want to change the behavior.  A good example of this is the `fmt_repeat` adaptor I use in this patch.  int already has a formatter defined for it, so if we want to repeat an int 10 times, we have no way to do that.  So we define a class `fmt_repeat` and give that a format member function, then instead of saying formatv("{0}", 7) we say formatv("{0}", fmt_repeat(7, 10));</div><div><br></div><div><br></div><div>Another point regarding F and D styles vs F.GetFilename() and F.GetDirectory().  One of the original design goals was brevity, because usually brevity helps readability.  To that end, I find </div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">formatv("Dir: {0:D}, File: {0:F}", F);</span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">more readable than</span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">formatv("Dir: {0}, File: {1}, F.</span><span style="color:rgb(33,33,33)">GetDirectory()</span><span style="color:rgb(33,33,33)">, F.</span><span style="color:rgb(33,33,33)">GetFilename()</span><span style="color:rgb(33,33,33)">);</span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">There's another, more subtle, advantage though.  If you just use GetFilename() and GetDirectory(), then what do you print if the string is empty?  Here we've got a simple string, no different from any other string, and an empty string is perfectly normal.  With specific types such as FileSpec, you know more about where that string came from, so you can make better decisions about how you want to handle the empty case (this argument applies to anything, not just strings, btw).  So now you either have to modify the core string formatter so that you can do something like this to specify an "empty" value:</span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">formatv("Dir: {0:(empty)}, File: {1:(empty)}", File.</span><span style="color:rgb(33,33,33)">GetDirectory()</span><span style="color:rgb(33,33,33)">, File.</span><span style="color:rgb(33,33,33)">GetFilename()</span><span style="color:rgb(33,33,33)">);</span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">or, even worse, you have to do this:</span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">formatv("Dir: {0}, File: {1}, File.GetFilename().IsEmpty() ? "(empty)" : File.GetFilename(), F.GetDirectory().IsEmpty() ? "(empty)" : F.GetDirectory());</span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">both are getting further and further away from the very simple and easy to read </span></div><div><span style="color:rgb(33,33,33)"><br></span></div><div><span style="color:rgb(33,33,33)">formatv("Dir: {0:D}, File: {0:F}", F);</span> </div><div><br></div><div>and both increase the possibility for errors and inconsistencies throughout the code whereas with the F and D styles, you guarantee that every time you ever print a FileSpec, it's always going to be consistent (of course, we could add an override mechanism to the FileSpec formatter as well if it were *really* necessary, but it seems best to try to avoid it as much as possible)<br></div></div><br><div class="gmail_quote"><div dir="ltr">On Sat, Dec 10, 2016 at 4:51 AM Zachary Turner <<a href="mailto:zturner@google.com">zturner@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I would say format provider should be the default way to add formatting for a commonly formatted type.  Member function syntax is used to implement adaptors that allow you to override formatting behavior of a type that already has a provider.<br class="gmail_msg"><br class="gmail_msg">One nice thing about F and D would be this:<br class="gmail_msg"><br class="gmail_msg">formatv("Dir: {0:D}, File: {0:F}", F):<br class="gmail_msg"><br class="gmail_msg">Here you only pass the argument once, but format it differently each time.  You do have a point about not getting a compiler error.  In the future i had planned to add compile time format string checking but it's a ways out.  For now we assert and then fallback to the default case of an empty style.<br class="gmail_msg"><br class="gmail_msg">Also, i still haven't finished the Args stuff, so no risk of me going on a reformatting spree :)<br class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Sat, Dec 10, 2016 at 1:03 AM Pavel Labath via Phabricator <<a href="mailto:reviews@reviews.llvm.org" class="gmail_msg" target="_blank">reviews@reviews.llvm.org</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">labath added a comment.<br class="gmail_msg">
<br class="gmail_msg">
This looks like a step in the right direction. I trust you won't go on a reformatting spree of the log messages until we settle on the syntax there. ;)<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
================<br class="gmail_msg">
Comment at: include/lldb/Core/ModuleSpec.h:244<br class="gmail_msg">
+      strm.Format("object_mod_time = {0:x+}",<br class="gmail_msg">
                   uint64_t(llvm::sys::toTimeT(m_object_mod_time)));<br class="gmail_msg">
     }<br class="gmail_msg">
----------------<br class="gmail_msg">
you can delete the `uint64_t` cast now. It was only there to make this portably printable.<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
================<br class="gmail_msg">
Comment at: include/lldb/Host/FileSpec.h:784<br class="gmail_msg">
+///<br class="gmail_msg">
+template <> struct format_provider<lldb_private::FileSpec> {<br class="gmail_msg">
+  static void format(const lldb_private::FileSpec &F, llvm::raw_ostream &Stream,<br class="gmail_msg">
----------------<br class="gmail_msg">
I am wondering.. what is the preferred style for adding formatting capability. I sort of assumed that the `format_provider` thingy was reserved for cases where you had no control over the object being formatted (e.g. because it comes from a third party library), and that for cases like this we would use the member format function (or, to put it differently: if we're going to be using the `format_provider` everywhere, what's the point of having the member functions in the first place?).<br class="gmail_msg">
<br class="gmail_msg">
Also, my preference would be to not have the F and D styles for FileSpec. I think they are redundant, as we have FileSpec::GetFilename and FileSpec::GetDirectory, and also they are not compiler-enforced --<br class="gmail_msg">
`Formatv('{0}', fs.GetFilename())` is slightly longer than `Formatv('{0:F}', fs)`, but if I make a typo in the former one, it will be a compiler error, while the other one won't. I suppose it could be useful, if one wants to format say an array of FileSpecs using the array format syntax, but I'm not sure how often will someone want to do that *and* display only the filenames.<br class="gmail_msg">
<br class="gmail_msg">
I don't care strongly about any of these things, but I want to know what to expect.<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
<a href="https://reviews.llvm.org/D27632" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D27632</a><br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
</blockquote></div></blockquote></div>