1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-25 10:41:16 +02:00

Use transparent comparators for std::set<std::string> (NFC)

This patch finally applies the transition to std::less<>,
which is a transparent comparator. There's no functional
change and string lookups in sets are now more efficient
and don't produce temporaries (e.g. set.find(std::string_view{"key"})).
This commit is contained in:
Sergei Zimmerman 2025-05-02 17:43:02 +00:00
parent 5278cd2396
commit ebb836d499
No known key found for this signature in database
GPG key ID: A9B0B557CA632325
12 changed files with 66 additions and 40 deletions

View file

@ -25,11 +25,11 @@ namespace nix {
LengthPrefixedProtoHelper<CommonProto, T >::write(store, conn, t); \ LengthPrefixedProtoHelper<CommonProto, T >::write(store, conn, t); \
} }
#define COMMA_ ,
COMMON_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::vector<T>) COMMON_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::vector<T>)
COMMON_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::set<T>) COMMON_USE_LENGTH_PREFIX_SERIALISER(template<typename T COMMA_ typename Compare>, std::set<T COMMA_ Compare>)
COMMON_USE_LENGTH_PREFIX_SERIALISER(template<typename... Ts>, std::tuple<Ts...>) COMMON_USE_LENGTH_PREFIX_SERIALISER(template<typename... Ts>, std::tuple<Ts...>)
#define COMMA_ ,
COMMON_USE_LENGTH_PREFIX_SERIALISER( COMMON_USE_LENGTH_PREFIX_SERIALISER(
template<typename K COMMA_ typename V>, template<typename K COMMA_ typename V>,
std::map<K COMMA_ V>) std::map<K COMMA_ V>)

View file

@ -72,14 +72,14 @@ DECLARE_COMMON_SERIALISER(DrvOutput);
template<> template<>
DECLARE_COMMON_SERIALISER(Realisation); DECLARE_COMMON_SERIALISER(Realisation);
#define COMMA_ ,
template<typename T> template<typename T>
DECLARE_COMMON_SERIALISER(std::vector<T>); DECLARE_COMMON_SERIALISER(std::vector<T>);
template<typename T> template<typename T, typename Compare>
DECLARE_COMMON_SERIALISER(std::set<T>); DECLARE_COMMON_SERIALISER(std::set<T COMMA_ Compare>);
template<typename... Ts> template<typename... Ts>
DECLARE_COMMON_SERIALISER(std::tuple<Ts...>); DECLARE_COMMON_SERIALISER(std::tuple<Ts...>);
#define COMMA_ ,
template<typename K, typename V> template<typename K, typename V>
DECLARE_COMMON_SERIALISER(std::map<K COMMA_ V>); DECLARE_COMMON_SERIALISER(std::map<K COMMA_ V>);
#undef COMMA_ #undef COMMA_

View file

@ -343,7 +343,7 @@ struct Derivation : BasicDerivation
/** /**
* inputs that are sub-derivations * inputs that are sub-derivations
*/ */
DerivedPathMap<std::set<OutputName>> inputDrvs; DerivedPathMap<std::set<OutputName, std::less<>>> inputDrvs;
/** /**
* Print a derivation. * Print a derivation.

View file

@ -52,8 +52,10 @@ struct LengthPrefixedProtoHelper;
template<class Inner, typename T> template<class Inner, typename T>
LENGTH_PREFIXED_PROTO_HELPER(Inner, std::vector<T>); LENGTH_PREFIXED_PROTO_HELPER(Inner, std::vector<T>);
template<class Inner, typename T> #define COMMA_ ,
LENGTH_PREFIXED_PROTO_HELPER(Inner, std::set<T>); template<class Inner, typename T, typename Compare>
LENGTH_PREFIXED_PROTO_HELPER(Inner, std::set<T COMMA_ Compare>);
#undef COMMA_
template<class Inner, typename... Ts> template<class Inner, typename... Ts>
LENGTH_PREFIXED_PROTO_HELPER(Inner, std::tuple<Ts...>); LENGTH_PREFIXED_PROTO_HELPER(Inner, std::tuple<Ts...>);
@ -86,12 +88,11 @@ LengthPrefixedProtoHelper<Inner, std::vector<T>>::write(
} }
} }
template<class Inner, typename T> template<class Inner, typename T, typename Compare>
std::set<T> std::set<T, Compare> LengthPrefixedProtoHelper<Inner, std::set<T, Compare>>::read(
LengthPrefixedProtoHelper<Inner, std::set<T>>::read(
const StoreDirConfig & store, typename Inner::ReadConn conn) const StoreDirConfig & store, typename Inner::ReadConn conn)
{ {
std::set<T> resSet; std::set<T, Compare> resSet;
auto size = readNum<size_t>(conn.from); auto size = readNum<size_t>(conn.from);
while (size--) { while (size--) {
resSet.insert(S<T>::read(store, conn)); resSet.insert(S<T>::read(store, conn));
@ -99,10 +100,9 @@ LengthPrefixedProtoHelper<Inner, std::set<T>>::read(
return resSet; return resSet;
} }
template<class Inner, typename T> template<class Inner, typename T, typename Compare>
void void LengthPrefixedProtoHelper<Inner, std::set<T, Compare>>::write(
LengthPrefixedProtoHelper<Inner, std::set<T>>::write( const StoreDirConfig & store, typename Inner::WriteConn conn, const std::set<T, Compare> & resSet)
const StoreDirConfig & store, typename Inner::WriteConn conn, const std::set<T> & resSet)
{ {
conn.to << resSet.size(); conn.to << resSet.size();
for (auto & key : resSet) { for (auto & key : resSet) {

View file

@ -27,20 +27,24 @@ struct OutputsSpec {
/** /**
* A non-empty set of outputs, specified by name * A non-empty set of outputs, specified by name
*/ */
struct Names : std::set<OutputName> { struct Names : std::set<OutputName, std::less<>> {
using std::set<OutputName>::set; private:
using BaseType = std::set<OutputName, std::less<>>;
public:
using BaseType::BaseType;
/* These need to be "inherited manually" */ /* These need to be "inherited manually" */
Names(const std::set<OutputName> & s) Names(const BaseType & s)
: std::set<OutputName>(s) : BaseType(s)
{ assert(!empty()); } { assert(!empty()); }
/** /**
* Needs to be "inherited manually" * Needs to be "inherited manually"
*/ */
Names(std::set<OutputName> && s) Names(BaseType && s)
: std::set<OutputName>(s) : BaseType(std::move(s))
{ assert(!empty()); } { assert(!empty()); }
/* This set should always be non-empty, so we delete this /* This set should always be non-empty, so we delete this

View file

@ -26,7 +26,9 @@ namespace nix {
} }
SERVE_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::vector<T>) SERVE_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::vector<T>)
SERVE_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::set<T>) #define COMMA_ ,
SERVE_USE_LENGTH_PREFIX_SERIALISER(template<typename T COMMA_ typename Compare>, std::set<T COMMA_ Compare>)
#undef COMMA_
SERVE_USE_LENGTH_PREFIX_SERIALISER(template<typename... Ts>, std::tuple<Ts...>) SERVE_USE_LENGTH_PREFIX_SERIALISER(template<typename... Ts>, std::tuple<Ts...>)
#define SERVE_USE_LENGTH_PREFIX_SERIALISER_COMMA , #define SERVE_USE_LENGTH_PREFIX_SERIALISER_COMMA ,

View file

@ -180,12 +180,12 @@ DECLARE_SERVE_SERIALISER(ServeProto::BuildOptions);
template<typename T> template<typename T>
DECLARE_SERVE_SERIALISER(std::vector<T>); DECLARE_SERVE_SERIALISER(std::vector<T>);
template<typename T> #define COMMA_ ,
DECLARE_SERVE_SERIALISER(std::set<T>); template<typename T, typename Compare>
DECLARE_SERVE_SERIALISER(std::set<T COMMA_ Compare>);
template<typename... Ts> template<typename... Ts>
DECLARE_SERVE_SERIALISER(std::tuple<Ts...>); DECLARE_SERVE_SERIALISER(std::tuple<Ts...>);
#define COMMA_ ,
template<typename K, typename V> template<typename K, typename V>
DECLARE_SERVE_SERIALISER(std::map<K COMMA_ V>); DECLARE_SERVE_SERIALISER(std::map<K COMMA_ V>);
#undef COMMA_ #undef COMMA_

View file

@ -26,7 +26,9 @@ namespace nix {
} }
WORKER_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::vector<T>) WORKER_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::vector<T>)
WORKER_USE_LENGTH_PREFIX_SERIALISER(template<typename T>, std::set<T>) #define COMMA_ ,
WORKER_USE_LENGTH_PREFIX_SERIALISER(template<typename T COMMA_ typename Compare>, std::set<T COMMA_ Compare>)
#undef COMMA_
WORKER_USE_LENGTH_PREFIX_SERIALISER(template<typename... Ts>, std::tuple<Ts...>) WORKER_USE_LENGTH_PREFIX_SERIALISER(template<typename... Ts>, std::tuple<Ts...>)
#define WORKER_USE_LENGTH_PREFIX_SERIALISER_COMMA , #define WORKER_USE_LENGTH_PREFIX_SERIALISER_COMMA ,

View file

@ -135,7 +135,7 @@ struct WorkerProto
} }
using Feature = std::string; using Feature = std::string;
using FeatureSet = std::set<Feature>; using FeatureSet = std::set<Feature, std::less<>>;
static const FeatureSet allFeatures; static const FeatureSet allFeatures;
}; };
@ -273,12 +273,12 @@ DECLARE_WORKER_SERIALISER(WorkerProto::ClientHandshakeInfo);
template<typename T> template<typename T>
DECLARE_WORKER_SERIALISER(std::vector<T>); DECLARE_WORKER_SERIALISER(std::vector<T>);
template<typename T> #define COMMA_ ,
DECLARE_WORKER_SERIALISER(std::set<T>); template<typename T, typename Compare>
DECLARE_WORKER_SERIALISER(std::set<T COMMA_ Compare>);
template<typename... Ts> template<typename... Ts>
DECLARE_WORKER_SERIALISER(std::tuple<Ts...>); DECLARE_WORKER_SERIALISER(std::tuple<Ts...>);
#define COMMA_ ,
template<typename K, typename V> template<typename K, typename V>
DECLARE_WORKER_SERIALISER(std::map<K COMMA_ V>); DECLARE_WORKER_SERIALISER(std::map<K COMMA_ V>);
#undef COMMA_ #undef COMMA_

View file

@ -90,8 +90,8 @@ struct json_avoids_null<std::vector<T>> : std::true_type {};
template<typename T> template<typename T>
struct json_avoids_null<std::list<T>> : std::true_type {}; struct json_avoids_null<std::list<T>> : std::true_type {};
template<typename T> template<typename T, typename Compare>
struct json_avoids_null<std::set<T>> : std::true_type {}; struct json_avoids_null<std::set<T, Compare>> : std::true_type {};
template<typename K, typename V> template<typename K, typename V>
struct json_avoids_null<std::map<K, V>> : std::true_type {}; struct json_avoids_null<std::map<K, V>> : std::true_type {};

View file

@ -5,13 +5,13 @@
namespace nix { namespace nix {
template<typename T> template<typename T, typename Compare>
std::vector<T> topoSort(std::set<T> items, std::vector<T> topoSort(std::set<T, Compare> items,
std::function<std::set<T>(const T &)> getChildren, std::function<std::set<T, Compare>(const T &)> getChildren,
std::function<Error(const T &, const T &)> makeCycleError) std::function<Error(const T &, const T &)> makeCycleError)
{ {
std::vector<T> sorted; std::vector<T> sorted;
std::set<T> visited, parents; decltype(items) visited, parents;
std::function<void(const T & path, const T * parent)> dfsVisit; std::function<void(const T & path, const T * parent)> dfsVisit;
@ -21,7 +21,7 @@ std::vector<T> topoSort(std::set<T> items,
if (!visited.insert(path).second) return; if (!visited.insert(path).second) return;
parents.insert(path); parents.insert(path);
std::set<T> references = getChildren(path); auto references = getChildren(path);
for (auto & i : references) for (auto & i : references)
/* Don't traverse into items that don't exist in our starting set. */ /* Don't traverse into items that don't exist in our starting set. */

View file

@ -12,17 +12,35 @@
namespace nix { namespace nix {
typedef std::list<std::string> Strings; typedef std::list<std::string> Strings;
typedef std::set<std::string> StringSet;
typedef std::map<std::string, std::string> StringMap; typedef std::map<std::string, std::string> StringMap;
typedef std::map<std::string, std::string> StringPairs; typedef std::map<std::string, std::string> StringPairs;
/**
* Alias to ordered set container with transparent comparator.
*
* Used instead of std::set<std::string> to use C++14 N3657 [1]
* heterogenous lookup consistently across the whole codebase.
* Transparent comparators get rid of creation of unnecessary
* temporary variables when looking up keys by `std::string_view`
* or C-style `const char *` strings.
*
* [1]: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3657.htm
*/
using StringSet = std::set<std::string, std::less<>>;
/** /**
* Paths are just strings. * Paths are just strings.
*/ */
typedef std::string Path; typedef std::string Path;
typedef std::string_view PathView; typedef std::string_view PathView;
typedef std::list<Path> Paths; typedef std::list<Path> Paths;
typedef std::set<Path> PathSet;
/**
* Alias to an ordered set of `Path`s. Uses transparent comparator.
*
* @see StringSet
*/
using PathSet = std::set<Path, std::less<>>;
typedef std::vector<std::pair<std::string, std::string>> Headers; typedef std::vector<std::pair<std::string, std::string>> Headers;