POC - Typed value assignment for different types.

Summary: TypedValue assignment operator=(TypedValue &other) is inefficient for types which already have a defined assignment operator, or can be assigned trivially, without using TypedValue to pass the value for assignment.

Reviewers: mislav.bradac, florijan, teon.banek

Reviewed By: florijan

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D934
This commit is contained in:
Dominik Gleich 2017-10-30 15:11:37 +01:00
parent f2aad117cf
commit 09ad52958f
2 changed files with 51 additions and 4 deletions

View File

@ -223,6 +223,31 @@ std::ostream &operator<<(std::ostream &os, const TypedValue &value) {
LOG(FATAL) << "Unsupported PropertyValue::Type";
}
#define DEFINE_TYPED_VALUE_ASSIGNMENT(type_param, typed_value_type, member) \
TypedValue &TypedValue::operator=(const type_param &other) { \
if (this->type_ == TypedValue::Type::typed_value_type) { \
this->member = other; \
} else { \
*this = TypedValue(other); \
} \
\
return *this; \
}
DEFINE_TYPED_VALUE_ASSIGNMENT(char *const, String, string_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(int, Int, int_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(bool, Bool, bool_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(int64_t, Int, int_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(double, Double, double_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(std::string, String, string_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(std::vector<TypedValue>, List, list_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(TypedValue::value_map_t, Map, map_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(VertexAccessor, Vertex, vertex_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(EdgeAccessor, Edge, edge_v)
DEFINE_TYPED_VALUE_ASSIGNMENT(Path, Path, path_v)
#undef DEFINE_TYPED_VALUE_ASSIGNMENT
TypedValue &TypedValue::operator=(const TypedValue &other) {
if (this != &other) {
this->~TypedValue();

View File

@ -108,8 +108,31 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
TypedValue(const Path &path) : type_(Type::Path) { new (&path_v) Path(path); }
TypedValue(const PropertyValue &value);
// assignment ops
TypedValue &operator=(const TypedValue &other);
/**
* There are all sorts of explicit assignments here because this way we avoid
* destructor and constructor of TypedValue for creating intermediary values,
* and can fill the typed value storage directly if it has the same underlying
* type.
*/
#define DECLARE_TYPED_VALUE_ASSIGNMENT(type_param) \
TypedValue &operator=(const type_param &other);
using value_map_t = std::map<std::string, TypedValue>;
// Don't delete char * const assignment because char* strings will be assigned
// using boolean assignment (not good).
DECLARE_TYPED_VALUE_ASSIGNMENT(char *const)
DECLARE_TYPED_VALUE_ASSIGNMENT(int)
DECLARE_TYPED_VALUE_ASSIGNMENT(bool)
DECLARE_TYPED_VALUE_ASSIGNMENT(int64_t)
DECLARE_TYPED_VALUE_ASSIGNMENT(double)
DECLARE_TYPED_VALUE_ASSIGNMENT(std::string)
DECLARE_TYPED_VALUE_ASSIGNMENT(std::vector<TypedValue>)
DECLARE_TYPED_VALUE_ASSIGNMENT(TypedValue::value_map_t)
DECLARE_TYPED_VALUE_ASSIGNMENT(VertexAccessor)
DECLARE_TYPED_VALUE_ASSIGNMENT(EdgeAccessor)
DECLARE_TYPED_VALUE_ASSIGNMENT(Path)
DECLARE_TYPED_VALUE_ASSIGNMENT(TypedValue)
#undef DECLARE_TYPED_VALUE_ASSIGNMENT
TypedValue(const TypedValue &other);
~TypedValue();
@ -129,7 +152,7 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
template <typename T>
const T &Value() const;
// TODO consider adding getters for primitives by value (and not by ref)
// TODO consider adding getters for primitives by value (and not by ref)
#define DECLARE_VALUE_AND_TYPE_GETTERS(type_param, field) \
/** Gets the value of type field. Throws if value is not field*/ \
@ -139,7 +162,6 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
/** Checks if it's the value is of the given type */ \
bool Is##field() const;
using value_map_t = std::map<std::string, TypedValue>;
DECLARE_VALUE_AND_TYPE_GETTERS(bool, Bool)
DECLARE_VALUE_AND_TYPE_GETTERS(int64_t, Int)
DECLARE_VALUE_AND_TYPE_GETTERS(double, Double)