mirror of
https://github.com/NixOS/nix
synced 2025-07-07 10:11:47 +02:00
libexpr: Format value.hh
The following commits will touch this file significantly, so it's better to get the formatting out of the way first.
This commit is contained in:
parent
04a731b4b9
commit
ea32580c9b
2 changed files with 158 additions and 87 deletions
|
@ -256,7 +256,6 @@
|
||||||
''^src/libexpr/include/nix/expr/value-to-json\.hh$''
|
''^src/libexpr/include/nix/expr/value-to-json\.hh$''
|
||||||
''^src/libexpr/value-to-xml\.cc$''
|
''^src/libexpr/value-to-xml\.cc$''
|
||||||
''^src/libexpr/include/nix/expr/value-to-xml\.hh$''
|
''^src/libexpr/include/nix/expr/value-to-xml\.hh$''
|
||||||
''^src/libexpr/include/nix/expr/value\.hh$''
|
|
||||||
''^src/libexpr/value/context\.cc$''
|
''^src/libexpr/value/context\.cc$''
|
||||||
''^src/libexpr/include/nix/expr/value/context\.hh$''
|
''^src/libexpr/include/nix/expr/value/context\.hh$''
|
||||||
''^src/libfetchers/attrs\.cc$''
|
''^src/libfetchers/attrs\.cc$''
|
||||||
|
|
|
@ -17,7 +17,6 @@ namespace nix {
|
||||||
struct Value;
|
struct Value;
|
||||||
class BindingsBuilder;
|
class BindingsBuilder;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
tUninitialized = 0,
|
tUninitialized = 0,
|
||||||
tInt = 1,
|
tInt = 1,
|
||||||
|
@ -54,7 +53,7 @@ typedef enum {
|
||||||
nAttrs,
|
nAttrs,
|
||||||
nList,
|
nList,
|
||||||
nFunction,
|
nFunction,
|
||||||
nExternal
|
nExternal,
|
||||||
} ValueType;
|
} ValueType;
|
||||||
|
|
||||||
class Bindings;
|
class Bindings;
|
||||||
|
@ -81,15 +80,15 @@ using NixFloat = double;
|
||||||
*/
|
*/
|
||||||
class ExternalValueBase
|
class ExternalValueBase
|
||||||
{
|
{
|
||||||
friend std::ostream & operator << (std::ostream & str, const ExternalValueBase & v);
|
friend std::ostream & operator<<(std::ostream & str, const ExternalValueBase & v);
|
||||||
friend class Printer;
|
friend class Printer;
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Print out the value
|
* Print out the value
|
||||||
*/
|
*/
|
||||||
virtual std::ostream & print(std::ostream & str) const = 0;
|
virtual std::ostream & print(std::ostream & str) const = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Return a simple string describing the type
|
* Return a simple string describing the type
|
||||||
*/
|
*/
|
||||||
|
@ -104,41 +103,44 @@ class ExternalValueBase
|
||||||
* Coerce the value to a string. Defaults to uncoercable, i.e. throws an
|
* Coerce the value to a string. Defaults to uncoercable, i.e. throws an
|
||||||
* error.
|
* error.
|
||||||
*/
|
*/
|
||||||
virtual std::string coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const;
|
virtual std::string coerceToString(
|
||||||
|
EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare to another value of the same type. Defaults to uncomparable,
|
* Compare to another value of the same type. Defaults to uncomparable,
|
||||||
* i.e. always false.
|
* i.e. always false.
|
||||||
*/
|
*/
|
||||||
virtual bool operator ==(const ExternalValueBase & b) const noexcept;
|
virtual bool operator==(const ExternalValueBase & b) const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the value as JSON. Defaults to unconvertable, i.e. throws an error
|
* Print the value as JSON. Defaults to unconvertable, i.e. throws an error
|
||||||
*/
|
*/
|
||||||
virtual nlohmann::json printValueAsJSON(EvalState & state, bool strict,
|
virtual nlohmann::json
|
||||||
NixStringContext & context, bool copyToStore = true) const;
|
printValueAsJSON(EvalState & state, bool strict, NixStringContext & context, bool copyToStore = true) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the value as XML. Defaults to unevaluated
|
* Print the value as XML. Defaults to unevaluated
|
||||||
*/
|
*/
|
||||||
virtual void printValueAsXML(EvalState & state, bool strict, bool location,
|
virtual void printValueAsXML(
|
||||||
XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
|
EvalState & state,
|
||||||
|
bool strict,
|
||||||
|
bool location,
|
||||||
|
XMLWriter & doc,
|
||||||
|
NixStringContext & context,
|
||||||
|
PathSet & drvsSeen,
|
||||||
const PosIdx pos) const;
|
const PosIdx pos) const;
|
||||||
|
|
||||||
virtual ~ExternalValueBase()
|
virtual ~ExternalValueBase() {};
|
||||||
{
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const ExternalValueBase & v);
|
std::ostream & operator<<(std::ostream & str, const ExternalValueBase & v);
|
||||||
|
|
||||||
|
|
||||||
class ListBuilder
|
class ListBuilder
|
||||||
{
|
{
|
||||||
const size_t size;
|
const size_t size;
|
||||||
Value * inlineElems[2] = {nullptr, nullptr};
|
Value * inlineElems[2] = {nullptr, nullptr};
|
||||||
public:
|
public:
|
||||||
Value * * elems;
|
Value ** elems;
|
||||||
ListBuilder(EvalState & state, size_t size);
|
ListBuilder(EvalState & state, size_t size);
|
||||||
|
|
||||||
// NOTE: Can be noexcept because we are just copying integral values and
|
// NOTE: Can be noexcept because we are just copying integral values and
|
||||||
|
@ -147,22 +149,28 @@ public:
|
||||||
: size(x.size)
|
: size(x.size)
|
||||||
, inlineElems{x.inlineElems[0], x.inlineElems[1]}
|
, inlineElems{x.inlineElems[0], x.inlineElems[1]}
|
||||||
, elems(size <= 2 ? inlineElems : x.elems)
|
, elems(size <= 2 ? inlineElems : x.elems)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Value * & operator [](size_t n)
|
Value *& operator[](size_t n)
|
||||||
{
|
{
|
||||||
return elems[n];
|
return elems[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Value * * iterator;
|
typedef Value ** iterator;
|
||||||
|
|
||||||
iterator begin() { return &elems[0]; }
|
iterator begin()
|
||||||
iterator end() { return &elems[size]; }
|
{
|
||||||
|
return &elems[0];
|
||||||
|
}
|
||||||
|
iterator end()
|
||||||
|
{
|
||||||
|
return &elems[size];
|
||||||
|
}
|
||||||
|
|
||||||
friend struct Value;
|
friend struct Value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Value
|
struct Value
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -177,21 +185,36 @@ public:
|
||||||
*/
|
*/
|
||||||
static Value * toPtr(SymbolStr str) noexcept;
|
static Value * toPtr(SymbolStr str) noexcept;
|
||||||
|
|
||||||
void print(EvalState &state, std::ostream &str, PrintOptions options = PrintOptions {});
|
void print(EvalState & state, std::ostream & str, PrintOptions options = PrintOptions{});
|
||||||
|
|
||||||
// Functions needed to distinguish the type
|
// Functions needed to distinguish the type
|
||||||
// These should be removed eventually, by putting the functionality that's
|
// These should be removed eventually, by putting the functionality that's
|
||||||
// needed by callers into methods of this type
|
// needed by callers into methods of this type
|
||||||
|
|
||||||
// type() == nThunk
|
// type() == nThunk
|
||||||
inline bool isThunk() const { return internalType == tThunk; };
|
inline bool isThunk() const
|
||||||
inline bool isApp() const { return internalType == tApp; };
|
{
|
||||||
|
return internalType == tThunk;
|
||||||
|
};
|
||||||
|
inline bool isApp() const
|
||||||
|
{
|
||||||
|
return internalType == tApp;
|
||||||
|
};
|
||||||
inline bool isBlackhole() const;
|
inline bool isBlackhole() const;
|
||||||
|
|
||||||
// type() == nFunction
|
// type() == nFunction
|
||||||
inline bool isLambda() const { return internalType == tLambda; };
|
inline bool isLambda() const
|
||||||
inline bool isPrimOp() const { return internalType == tPrimOp; };
|
{
|
||||||
inline bool isPrimOpApp() const { return internalType == tPrimOpApp; };
|
return internalType == tLambda;
|
||||||
|
};
|
||||||
|
inline bool isPrimOp() const
|
||||||
|
{
|
||||||
|
return internalType == tPrimOp;
|
||||||
|
};
|
||||||
|
inline bool isPrimOpApp() const
|
||||||
|
{
|
||||||
|
return internalType == tPrimOpApp;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strings in the evaluator carry a so-called `context` which
|
* Strings in the evaluator carry a so-called `context` which
|
||||||
|
@ -215,26 +238,31 @@ public:
|
||||||
|
|
||||||
* For canonicity, the store paths should be in sorted order.
|
* For canonicity, the store paths should be in sorted order.
|
||||||
*/
|
*/
|
||||||
struct StringWithContext {
|
struct StringWithContext
|
||||||
|
{
|
||||||
const char * c_str;
|
const char * c_str;
|
||||||
const char * * context; // must be in sorted order
|
const char ** context; // must be in sorted order
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Path {
|
struct Path
|
||||||
|
{
|
||||||
SourceAccessor * accessor;
|
SourceAccessor * accessor;
|
||||||
const char * path;
|
const char * path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClosureThunk {
|
struct ClosureThunk
|
||||||
|
{
|
||||||
Env * env;
|
Env * env;
|
||||||
Expr * expr;
|
Expr * expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionApplicationThunk {
|
struct FunctionApplicationThunk
|
||||||
Value * left, * right;
|
{
|
||||||
|
Value *left, *right;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Lambda {
|
struct Lambda
|
||||||
|
{
|
||||||
Env * env;
|
Env * env;
|
||||||
ExprLambda * fun;
|
ExprLambda * fun;
|
||||||
};
|
};
|
||||||
|
@ -249,7 +277,8 @@ public:
|
||||||
Path path;
|
Path path;
|
||||||
|
|
||||||
Bindings * attrs;
|
Bindings * attrs;
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
Value * const * elems;
|
Value * const * elems;
|
||||||
} bigList;
|
} bigList;
|
||||||
|
@ -275,18 +304,35 @@ public:
|
||||||
inline ValueType type(bool invalidIsThunk = false) const
|
inline ValueType type(bool invalidIsThunk = false) const
|
||||||
{
|
{
|
||||||
switch (internalType) {
|
switch (internalType) {
|
||||||
case tUninitialized: break;
|
case tUninitialized:
|
||||||
case tInt: return nInt;
|
break;
|
||||||
case tBool: return nBool;
|
case tInt:
|
||||||
case tString: return nString;
|
return nInt;
|
||||||
case tPath: return nPath;
|
case tBool:
|
||||||
case tNull: return nNull;
|
return nBool;
|
||||||
case tAttrs: return nAttrs;
|
case tString:
|
||||||
case tList1: case tList2: case tListN: return nList;
|
return nString;
|
||||||
case tLambda: case tPrimOp: case tPrimOpApp: return nFunction;
|
case tPath:
|
||||||
case tExternal: return nExternal;
|
return nPath;
|
||||||
case tFloat: return nFloat;
|
case tNull:
|
||||||
case tThunk: case tApp: return nThunk;
|
return nNull;
|
||||||
|
case tAttrs:
|
||||||
|
return nAttrs;
|
||||||
|
case tList1:
|
||||||
|
case tList2:
|
||||||
|
case tListN:
|
||||||
|
return nList;
|
||||||
|
case tLambda:
|
||||||
|
case tPrimOp:
|
||||||
|
case tPrimOpApp:
|
||||||
|
return nFunction;
|
||||||
|
case tExternal:
|
||||||
|
return nExternal;
|
||||||
|
case tFloat:
|
||||||
|
return nFloat;
|
||||||
|
case tThunk:
|
||||||
|
case tApp:
|
||||||
|
return nThunk;
|
||||||
}
|
}
|
||||||
if (invalidIsThunk)
|
if (invalidIsThunk)
|
||||||
return nThunk;
|
return nThunk;
|
||||||
|
@ -317,17 +363,17 @@ public:
|
||||||
|
|
||||||
inline void mkInt(NixInt n)
|
inline void mkInt(NixInt n)
|
||||||
{
|
{
|
||||||
finishValue(tInt, { .integer = n });
|
finishValue(tInt, {.integer = n});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkBool(bool b)
|
inline void mkBool(bool b)
|
||||||
{
|
{
|
||||||
finishValue(tBool, { .boolean = b });
|
finishValue(tBool, {.boolean = b});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkString(const char * s, const char * * context = 0)
|
inline void mkString(const char * s, const char ** context = 0)
|
||||||
{
|
{
|
||||||
finishValue(tString, { .string = { .c_str = s, .context = context } });
|
finishValue(tString, {.string = {.c_str = s, .context = context}});
|
||||||
}
|
}
|
||||||
|
|
||||||
void mkString(std::string_view s);
|
void mkString(std::string_view s);
|
||||||
|
@ -341,7 +387,7 @@ public:
|
||||||
|
|
||||||
inline void mkPath(SourceAccessor * accessor, const char * path)
|
inline void mkPath(SourceAccessor * accessor, const char * path)
|
||||||
{
|
{
|
||||||
finishValue(tPath, { .path = { .accessor = accessor, .path = path } });
|
finishValue(tPath, {.path = {.accessor = accessor, .path = path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkNull()
|
inline void mkNull()
|
||||||
|
@ -351,7 +397,7 @@ public:
|
||||||
|
|
||||||
inline void mkAttrs(Bindings * a)
|
inline void mkAttrs(Bindings * a)
|
||||||
{
|
{
|
||||||
finishValue(tAttrs, { .attrs = a });
|
finishValue(tAttrs, {.attrs = a});
|
||||||
}
|
}
|
||||||
|
|
||||||
Value & mkAttrs(BindingsBuilder & bindings);
|
Value & mkAttrs(BindingsBuilder & bindings);
|
||||||
|
@ -359,26 +405,26 @@ public:
|
||||||
void mkList(const ListBuilder & builder)
|
void mkList(const ListBuilder & builder)
|
||||||
{
|
{
|
||||||
if (builder.size == 1)
|
if (builder.size == 1)
|
||||||
finishValue(tList1, { .smallList = { builder.inlineElems[0] } });
|
finishValue(tList1, {.smallList = {builder.inlineElems[0]}});
|
||||||
else if (builder.size == 2)
|
else if (builder.size == 2)
|
||||||
finishValue(tList2, { .smallList = { builder.inlineElems[0], builder.inlineElems[1] } });
|
finishValue(tList2, {.smallList = {builder.inlineElems[0], builder.inlineElems[1]}});
|
||||||
else
|
else
|
||||||
finishValue(tListN, { .bigList = { .size = builder.size, .elems = builder.elems } });
|
finishValue(tListN, {.bigList = {.size = builder.size, .elems = builder.elems}});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkThunk(Env * e, Expr * ex)
|
inline void mkThunk(Env * e, Expr * ex)
|
||||||
{
|
{
|
||||||
finishValue(tThunk, { .thunk = { .env = e, .expr = ex } });
|
finishValue(tThunk, {.thunk = {.env = e, .expr = ex}});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkApp(Value * l, Value * r)
|
inline void mkApp(Value * l, Value * r)
|
||||||
{
|
{
|
||||||
finishValue(tApp, { .app = { .left = l, .right = r } });
|
finishValue(tApp, {.app = {.left = l, .right = r}});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkLambda(Env * e, ExprLambda * f)
|
inline void mkLambda(Env * e, ExprLambda * f)
|
||||||
{
|
{
|
||||||
finishValue(tLambda, { .lambda = { .env = e, .fun = f } });
|
finishValue(tLambda, {.lambda = {.env = e, .fun = f}});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkBlackhole();
|
inline void mkBlackhole();
|
||||||
|
@ -387,7 +433,7 @@ public:
|
||||||
|
|
||||||
inline void mkPrimOpApp(Value * l, Value * r)
|
inline void mkPrimOpApp(Value * l, Value * r)
|
||||||
{
|
{
|
||||||
finishValue(tPrimOpApp, { .primOpApp = { .left = l, .right = r } });
|
finishValue(tPrimOpApp, {.primOpApp = {.left = l, .right = r}});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -397,12 +443,12 @@ public:
|
||||||
|
|
||||||
inline void mkExternal(ExternalValueBase * e)
|
inline void mkExternal(ExternalValueBase * e)
|
||||||
{
|
{
|
||||||
finishValue(tExternal, { .external = e });
|
finishValue(tExternal, {.external = e});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkFloat(NixFloat n)
|
inline void mkFloat(NixFloat n)
|
||||||
{
|
{
|
||||||
finishValue(tFloat, { .fpoint = n });
|
finishValue(tFloat, {.fpoint = n});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isList() const
|
bool isList() const
|
||||||
|
@ -438,9 +484,7 @@ public:
|
||||||
SourcePath path() const
|
SourcePath path() const
|
||||||
{
|
{
|
||||||
assert(internalType == tPath);
|
assert(internalType == tPath);
|
||||||
return SourcePath(
|
return SourcePath(ref(pathAccessor()->shared_from_this()), CanonPath(CanonPath::unchecked_t(), pathStr()));
|
||||||
ref(pathAccessor()->shared_from_this()),
|
|
||||||
CanonPath(CanonPath::unchecked_t(), pathStr()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view string_view() const
|
std::string_view string_view() const
|
||||||
|
@ -455,54 +499,77 @@ public:
|
||||||
return payload.string.c_str;
|
return payload.string.c_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * * context() const
|
const char ** context() const
|
||||||
{
|
{
|
||||||
return payload.string.context;
|
return payload.string.context;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalValueBase * external() const
|
ExternalValueBase * external() const
|
||||||
{ return payload.external; }
|
{
|
||||||
|
return payload.external;
|
||||||
|
}
|
||||||
|
|
||||||
const Bindings * attrs() const
|
const Bindings * attrs() const
|
||||||
{ return payload.attrs; }
|
{
|
||||||
|
return payload.attrs;
|
||||||
|
}
|
||||||
|
|
||||||
const PrimOp * primOp() const
|
const PrimOp * primOp() const
|
||||||
{ return payload.primOp; }
|
{
|
||||||
|
return payload.primOp;
|
||||||
|
}
|
||||||
|
|
||||||
bool boolean() const
|
bool boolean() const
|
||||||
{ return payload.boolean; }
|
{
|
||||||
|
return payload.boolean;
|
||||||
|
}
|
||||||
|
|
||||||
NixInt integer() const
|
NixInt integer() const
|
||||||
{ return payload.integer; }
|
{
|
||||||
|
return payload.integer;
|
||||||
|
}
|
||||||
|
|
||||||
NixFloat fpoint() const
|
NixFloat fpoint() const
|
||||||
{ return payload.fpoint; }
|
{
|
||||||
|
return payload.fpoint;
|
||||||
|
}
|
||||||
|
|
||||||
Lambda lambda() const
|
Lambda lambda() const
|
||||||
{ return payload.lambda; }
|
{
|
||||||
|
return payload.lambda;
|
||||||
|
}
|
||||||
|
|
||||||
ClosureThunk thunk() const
|
ClosureThunk thunk() const
|
||||||
{ return payload.thunk; }
|
{
|
||||||
|
return payload.thunk;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionApplicationThunk primOpApp() const
|
FunctionApplicationThunk primOpApp() const
|
||||||
{ return payload.primOpApp; }
|
{
|
||||||
|
return payload.primOpApp;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionApplicationThunk app() const
|
FunctionApplicationThunk app() const
|
||||||
{ return payload.app; }
|
{
|
||||||
|
return payload.app;
|
||||||
|
}
|
||||||
|
|
||||||
const char * pathStr() const
|
const char * pathStr() const
|
||||||
{ return payload.path.path; }
|
{
|
||||||
|
return payload.path.path;
|
||||||
|
}
|
||||||
|
|
||||||
SourceAccessor * pathAccessor() const
|
SourceAccessor * pathAccessor() const
|
||||||
{ return payload.path.accessor; }
|
{
|
||||||
|
return payload.path.accessor;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern ExprBlackHole eBlackHole;
|
extern ExprBlackHole eBlackHole;
|
||||||
|
|
||||||
bool Value::isBlackhole() const
|
bool Value::isBlackhole() const
|
||||||
{
|
{
|
||||||
return internalType == tThunk && thunk().expr == (Expr*) &eBlackHole;
|
return internalType == tThunk && thunk().expr == (Expr *) &eBlackHole;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::mkBlackhole()
|
void Value::mkBlackhole()
|
||||||
|
@ -510,11 +577,16 @@ void Value::mkBlackhole()
|
||||||
mkThunk(nullptr, (Expr *) &eBlackHole);
|
mkThunk(nullptr, (Expr *) &eBlackHole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef std::vector<Value *, traceable_allocator<Value *>> ValueVector;
|
typedef std::vector<Value *, traceable_allocator<Value *>> ValueVector;
|
||||||
typedef std::unordered_map<Symbol, Value *, std::hash<Symbol>, std::equal_to<Symbol>, traceable_allocator<std::pair<const Symbol, Value *>>> ValueMap;
|
typedef std::unordered_map<
|
||||||
typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector>>> ValueVectorMap;
|
Symbol,
|
||||||
|
Value *,
|
||||||
|
std::hash<Symbol>,
|
||||||
|
std::equal_to<Symbol>,
|
||||||
|
traceable_allocator<std::pair<const Symbol, Value *>>>
|
||||||
|
ValueMap;
|
||||||
|
typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector>>>
|
||||||
|
ValueVectorMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A value allocated in traceable memory.
|
* A value allocated in traceable memory.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue