lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] [lmi-commits] master 58b0c04 3/9: Sort columns alphabetically


From: Greg Chicares
Subject: Re: [lmi] [lmi-commits] master 58b0c04 3/9: Sort columns alphabetically in TSV output
Date: Fri, 28 Sep 2018 00:23:36 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1

On 2018-09-27 20:37, Vadim Zeitlin wrote:
> On Thu, 27 Sep 2018 12:53:50 -0400 (EDT) Greg Chicares <address@hidden> wrote:
[...]
> GC> +        std::map<std::string,std::vector<std::string>> 
> ordered_stringvectors
> GC> +            (stringvectors.begin()
> GC> +            ,stringvectors.end()
> GC> +            );
> 
>  That's another nitpick, but shouldn't be the parentheses above be braces,
> i.e.
> 
>       std::map<std::string,std::vector<std::string>> ordered_stringvectors
>           {stringvectors.begin()
>           ,stringvectors.end()
>           };
> 
> ? I don't think we can get into trouble with the initializer list ctor
> overload here, as an iterator shouldn't be convertible to a pair (I hope?),
> but please let me know if I'm missing anything.

Our discussions on this topic are still evolving, and there's room for
them to evolve further; but IIRC the closest we've come to a rule is
to use () when we're "calling" a special member function, as in
  std::vector<int> v(10, 7); // Calls vector::vector(int len, T value).
and to use {} when we're "moving" or "copying" a value, e.g.:
  std::vector<int> v2 {v1};  // Calls vector::vector(vector const&).

In this case, I'd say we're calling a ctor:
  map::map(iterator, iterator);
An iterator isn't a map, so we aren't "moving" or "copying" its
arguments; we're calling the ctor with those arguments, so it's more
like a function call IMO.

Another way to put this is: use {} for operations that a fairly simple
compiler could be expected to optimize away, and () for operations
that require real work to be done (unless the optimizer is very
sophisticated). Here, I expect that at runtime the hashmap will be
traversed and an RB tree will be constructed on the fly.

A stronger criterion (which I'm not entirely convinced is appropriate)
would be to use {} iff assignment makes the LHS and RHS identical in
the sense that if
  T lhs = {rhs};
then there's no way to write a function f<T>() that gives different
results for f(lhs) and f(rhs). Of course that wouldn't be satisfied
here because std::map and std::unordered_map are different types.

IIUC, you're suggesting a different rule: use {} unless it would be
semantically incorrect--i.e., almost always. I'm not sure what
"almost always" means; I only know that std::vector(count, value)
is one exception, but I don't know what other exceptions may be
necessary.

>  And, while I'm nitpicking, shouldn't the ordered_stringvectors be const?

Agreed: commit 5e45c3d48.

>  Also, I don't mind sorting unordered map in such a way, but I think that
> if we need to do it just one more time, it would be worth adding some
> make_sorted() template function with the trivial implementation that could
> be used to write just
> 
>       auto const ordered_stringvectors = make_sorted(stringvectors);

That might convert unordered containers to their sorted analogues.
We could alternatively consider a bidirectional converter; or
maybe a general converter between "compatible" containers, but
perhaps there's no use case for, e.g., converting a list to a deque.

> instead of having to write all the 46 characters of the map type
> explicitly.

00000000011111111112222222222333333333344444444445555555555666666666677777777778
12345678901234567890123456789012345678901234567890123456789012345678901234567890
std::map<std::string,std::vector<std::string>> ordered_stringvectors

At least I didn't use std::basic_string<...>.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]