TypedValue getters return references
Reviewers: buda Reviewed By: buda Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D113
This commit is contained in:
parent
3e0b12f646
commit
a5a15673de
@ -1,58 +1,58 @@
|
|||||||
#include "query/backend/cpp/typed_value.hpp"
|
#include "query/backend/cpp/typed_value.hpp"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "utils/assert.hpp"
|
#include "utils/assert.hpp"
|
||||||
|
|
||||||
TypedValue::TypedValue(const PropertyValue& value) {
|
TypedValue::TypedValue(const PropertyValue &value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case PropertyValue::Type::Null:
|
case PropertyValue::Type::Null:
|
||||||
type_ = Type::Null;
|
type_ = Type::Null;
|
||||||
return;
|
return;
|
||||||
case PropertyValue::Type::Bool:
|
case PropertyValue::Type::Bool:
|
||||||
type_ = Type::Bool;
|
type_ = Type::Bool;
|
||||||
bool_v = value.Value<bool>();
|
bool_v = value.Value<bool>();
|
||||||
return;
|
return;
|
||||||
case PropertyValue::Type::Int:
|
case PropertyValue::Type::Int:
|
||||||
type_ = Type::Int;
|
type_ = Type::Int;
|
||||||
int_v = value.Value<int64_t>();
|
int_v = value.Value<int64_t>();
|
||||||
return;
|
return;
|
||||||
case PropertyValue::Type::Double:
|
case PropertyValue::Type::Double:
|
||||||
type_ = Type::Double;
|
type_ = Type::Double;
|
||||||
double_v = value.Value<double>();
|
double_v = value.Value<double>();
|
||||||
case PropertyValue::Type::String:
|
case PropertyValue::Type::String:
|
||||||
type_ = Type::String;
|
type_ = Type::String;
|
||||||
new (&string_v) std::string(value.Value<std::string>());
|
new (&string_v) std::string(value.Value<std::string>());
|
||||||
case PropertyValue::Type::List:
|
case PropertyValue::Type::List:
|
||||||
type_ = Type::List;
|
type_ = Type::List;
|
||||||
auto vec = value.Value<std::vector<PropertyValue>>();
|
auto vec = value.Value<std::vector<PropertyValue>>();
|
||||||
new (&list_v) std::vector<TypedValue>(vec.begin(), vec.end());
|
new (&list_v) std::vector<TypedValue>(vec.begin(), vec.end());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
permanent_fail("Unsupported type");
|
permanent_fail("Unsupported type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue::operator PropertyValue() const {
|
TypedValue::operator PropertyValue() const {
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case TypedValue::Type::Null:
|
case TypedValue::Type::Null:
|
||||||
return PropertyValue::Null;
|
return PropertyValue::Null;
|
||||||
case TypedValue::Type::Bool:
|
case TypedValue::Type::Bool:
|
||||||
return PropertyValue(bool_v);
|
return PropertyValue(bool_v);
|
||||||
case TypedValue::Type::Int:
|
case TypedValue::Type::Int:
|
||||||
return PropertyValue(int_v);
|
return PropertyValue(int_v);
|
||||||
case TypedValue::Type::Double:
|
case TypedValue::Type::Double:
|
||||||
return PropertyValue(double_v);
|
return PropertyValue(double_v);
|
||||||
case TypedValue::Type::String:
|
case TypedValue::Type::String:
|
||||||
return PropertyValue(string_v);
|
return PropertyValue(string_v);
|
||||||
case TypedValue::Type::List:
|
case TypedValue::Type::List:
|
||||||
return PropertyValue(
|
return PropertyValue(
|
||||||
std::vector<PropertyValue>(list_v.begin(), list_v.end()));
|
std::vector<PropertyValue>(list_v.begin(), list_v.end()));
|
||||||
default:
|
default:
|
||||||
throw TypedValueException(
|
throw TypedValueException(
|
||||||
"Unsupported conversion from TypedValue to PropertyValue");
|
"Unsupported conversion from TypedValue to PropertyValue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,32 +61,28 @@ TypedValue::operator PropertyValue() const {
|
|||||||
// Other solution would be to add additional overloads for references, for
|
// Other solution would be to add additional overloads for references, for
|
||||||
// example Value<string&>.
|
// example Value<string&>.
|
||||||
// Value extraction template instantiations
|
// Value extraction template instantiations
|
||||||
template <>
|
template <> const bool &TypedValue::Value<bool>() const {
|
||||||
bool TypedValue::Value<bool>() const {
|
|
||||||
if (type_ != TypedValue::Type::Bool) {
|
if (type_ != TypedValue::Type::Bool) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
return bool_v;
|
return bool_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> const int64_t &TypedValue::Value<int64_t>() const {
|
||||||
int64_t TypedValue::Value<int64_t>() const {
|
|
||||||
if (type_ != TypedValue::Type::Int) {
|
if (type_ != TypedValue::Type::Int) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
return int_v;
|
return int_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> const double &TypedValue::Value<double>() const {
|
||||||
double TypedValue::Value<double>() const {
|
|
||||||
if (type_ != TypedValue::Type::Double) {
|
if (type_ != TypedValue::Type::Double) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
return double_v;
|
return double_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> const std::string &TypedValue::Value<std::string>() const {
|
||||||
std::string TypedValue::Value<std::string>() const {
|
|
||||||
if (type_ != TypedValue::Type::String) {
|
if (type_ != TypedValue::Type::String) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
@ -94,7 +90,8 @@ std::string TypedValue::Value<std::string>() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::vector<TypedValue> TypedValue::Value<std::vector<TypedValue>>() const {
|
const std::vector<TypedValue> &
|
||||||
|
TypedValue::Value<std::vector<TypedValue>>() const {
|
||||||
if (type_ != TypedValue::Type::List) {
|
if (type_ != TypedValue::Type::List) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
@ -102,7 +99,7 @@ std::vector<TypedValue> TypedValue::Value<std::vector<TypedValue>>() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::map<std::string, TypedValue>
|
std::map<std::string, TypedValue> const &
|
||||||
TypedValue::Value<std::map<std::string, TypedValue>>() const {
|
TypedValue::Value<std::map<std::string, TypedValue>>() const {
|
||||||
if (type_ != TypedValue::Type::Map) {
|
if (type_ != TypedValue::Type::Map) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
@ -110,159 +107,222 @@ TypedValue::Value<std::map<std::string, TypedValue>>() const {
|
|||||||
return map_v;
|
return map_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> const VertexAccessor &TypedValue::Value<VertexAccessor>() const {
|
||||||
VertexAccessor TypedValue::Value<VertexAccessor>() const {
|
|
||||||
if (type_ != TypedValue::Type::Vertex) {
|
if (type_ != TypedValue::Type::Vertex) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
return vertex_v;
|
return vertex_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> const EdgeAccessor &TypedValue::Value<EdgeAccessor>() const {
|
||||||
EdgeAccessor TypedValue::Value<EdgeAccessor>() const {
|
|
||||||
if (type_ != TypedValue::Type::Edge) {
|
if (type_ != TypedValue::Type::Edge) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
return edge_v;
|
return edge_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <> const Path &TypedValue::Value<Path>() const {
|
||||||
Path TypedValue::Value<Path>() const {
|
|
||||||
if (type_ != TypedValue::Type::Path) {
|
if (type_ != TypedValue::Type::Path) {
|
||||||
throw TypedValueException("Incompatible template param and type");
|
throw TypedValueException("Incompatible template param and type");
|
||||||
}
|
}
|
||||||
return path_v;
|
return path_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue::TypedValue(const TypedValue& other) : type_(other.type_) {
|
template <> bool &TypedValue::Value<bool>() {
|
||||||
|
if (type_ != TypedValue::Type::Bool) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return bool_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> int64_t &TypedValue::Value<int64_t>() {
|
||||||
|
if (type_ != TypedValue::Type::Int) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return int_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> double &TypedValue::Value<double>() {
|
||||||
|
if (type_ != TypedValue::Type::Double) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return double_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> std::string &TypedValue::Value<std::string>() {
|
||||||
|
if (type_ != TypedValue::Type::String) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return string_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::vector<TypedValue> &TypedValue::Value<std::vector<TypedValue>>() {
|
||||||
|
if (type_ != TypedValue::Type::List) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return list_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
std::map<std::string, TypedValue> &
|
||||||
|
TypedValue::Value<std::map<std::string, TypedValue>>() {
|
||||||
|
if (type_ != TypedValue::Type::Map) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return map_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> VertexAccessor &TypedValue::Value<VertexAccessor>() {
|
||||||
|
if (type_ != TypedValue::Type::Vertex) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return vertex_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> EdgeAccessor &TypedValue::Value<EdgeAccessor>() {
|
||||||
|
if (type_ != TypedValue::Type::Edge) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return edge_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> Path &TypedValue::Value<Path>() {
|
||||||
|
if (type_ != TypedValue::Type::Path) {
|
||||||
|
throw TypedValueException("Incompatible template param and type");
|
||||||
|
}
|
||||||
|
return path_v;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypedValue::TypedValue(const TypedValue &other) : type_(other.type_) {
|
||||||
switch (other.type_) {
|
switch (other.type_) {
|
||||||
case TypedValue::Type::Null:
|
case TypedValue::Type::Null:
|
||||||
return;
|
return;
|
||||||
case TypedValue::Type::Bool:
|
case TypedValue::Type::Bool:
|
||||||
this->bool_v = other.bool_v;
|
this->bool_v = other.bool_v;
|
||||||
return;
|
return;
|
||||||
case Type::Int:
|
case Type::Int:
|
||||||
this->int_v = other.int_v;
|
this->int_v = other.int_v;
|
||||||
return;
|
return;
|
||||||
case Type::Double:
|
case Type::Double:
|
||||||
this->double_v = other.double_v;
|
this->double_v = other.double_v;
|
||||||
return;
|
return;
|
||||||
case TypedValue::Type::String:
|
case TypedValue::Type::String:
|
||||||
new (&string_v) std::string(other.string_v);
|
new (&string_v) std::string(other.string_v);
|
||||||
return;
|
return;
|
||||||
case Type::List:
|
case Type::List:
|
||||||
new (&list_v) std::vector<TypedValue>(other.list_v);
|
new (&list_v) std::vector<TypedValue>(other.list_v);
|
||||||
return;
|
return;
|
||||||
case Type::Map:
|
case Type::Map:
|
||||||
new (&map_v) std::map<std::string, TypedValue>(other.map_v);
|
new (&map_v) std::map<std::string, TypedValue>(other.map_v);
|
||||||
return;
|
return;
|
||||||
case Type::Vertex:
|
case Type::Vertex:
|
||||||
new (&vertex_v) VertexAccessor(other.vertex_v);
|
new (&vertex_v) VertexAccessor(other.vertex_v);
|
||||||
return;
|
return;
|
||||||
case Type::Edge:
|
case Type::Edge:
|
||||||
new (&edge_v) EdgeAccessor(other.edge_v);
|
new (&edge_v) EdgeAccessor(other.edge_v);
|
||||||
return;
|
return;
|
||||||
case Type::Path:
|
case Type::Path:
|
||||||
new (&path_v) Path(other.path_v);
|
new (&path_v) Path(other.path_v);
|
||||||
}
|
}
|
||||||
permanent_fail("Unsupported TypedValue::Type");
|
permanent_fail("Unsupported TypedValue::Type");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const TypedValue::Type type) {
|
std::ostream &operator<<(std::ostream &os, const TypedValue::Type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TypedValue::Type::Null:
|
case TypedValue::Type::Null:
|
||||||
return os << "null";
|
return os << "null";
|
||||||
case TypedValue::Type::Bool:
|
case TypedValue::Type::Bool:
|
||||||
return os << "bool";
|
return os << "bool";
|
||||||
case TypedValue::Type::Int:
|
case TypedValue::Type::Int:
|
||||||
return os << "int";
|
return os << "int";
|
||||||
case TypedValue::Type::Double:
|
case TypedValue::Type::Double:
|
||||||
return os << "double";
|
return os << "double";
|
||||||
case TypedValue::Type::String:
|
case TypedValue::Type::String:
|
||||||
return os << "string";
|
return os << "string";
|
||||||
case TypedValue::Type::List:
|
case TypedValue::Type::List:
|
||||||
return os << "list";
|
return os << "list";
|
||||||
case TypedValue::Type::Map:
|
case TypedValue::Type::Map:
|
||||||
return os << "map";
|
return os << "map";
|
||||||
case TypedValue::Type::Vertex:
|
case TypedValue::Type::Vertex:
|
||||||
return os << "vertex";
|
return os << "vertex";
|
||||||
case TypedValue::Type::Edge:
|
case TypedValue::Type::Edge:
|
||||||
return os << "edge";
|
return os << "edge";
|
||||||
case TypedValue::Type::Path:
|
case TypedValue::Type::Path:
|
||||||
return os << "path";
|
return os << "path";
|
||||||
}
|
}
|
||||||
permanent_fail("Unsupported TypedValue::Type");
|
permanent_fail("Unsupported TypedValue::Type");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const TypedValue& value) {
|
std::ostream &operator<<(std::ostream &os, const TypedValue &value) {
|
||||||
switch (value.type_) {
|
switch (value.type_) {
|
||||||
case TypedValue::Type::Null:
|
case TypedValue::Type::Null:
|
||||||
return os << "Null";
|
return os << "Null";
|
||||||
case TypedValue::Type::Bool:
|
case TypedValue::Type::Bool:
|
||||||
return os << (value.Value<bool>() ? "true" : "false");
|
return os << (value.Value<bool>() ? "true" : "false");
|
||||||
case TypedValue::Type::Int:
|
case TypedValue::Type::Int:
|
||||||
return os << value.Value<int64_t>();
|
return os << value.Value<int64_t>();
|
||||||
case TypedValue::Type::Double:
|
case TypedValue::Type::Double:
|
||||||
return os << value.Value<double>();
|
return os << value.Value<double>();
|
||||||
case TypedValue::Type::String:
|
case TypedValue::Type::String:
|
||||||
return os << value.Value<std::string>();
|
return os << value.Value<std::string>();
|
||||||
case TypedValue::Type::List:
|
case TypedValue::Type::List:
|
||||||
os << "[";
|
os << "[";
|
||||||
for (const auto& x : value.Value<std::vector<TypedValue>>()) {
|
for (const auto &x : value.Value<std::vector<TypedValue>>()) {
|
||||||
os << x << ",";
|
os << x << ",";
|
||||||
}
|
}
|
||||||
return os << "]";
|
return os << "]";
|
||||||
case TypedValue::Type::Map:
|
case TypedValue::Type::Map:
|
||||||
os << "{";
|
os << "{";
|
||||||
for (const auto& x : value.Value<std::map<std::string, TypedValue>>()) {
|
for (const auto &x : value.Value<std::map<std::string, TypedValue>>()) {
|
||||||
os << x.first << ": " << x.second << ",";
|
os << x.first << ": " << x.second << ",";
|
||||||
}
|
}
|
||||||
return os << "}";
|
return os << "}";
|
||||||
case TypedValue::Type::Vertex:
|
case TypedValue::Type::Vertex:
|
||||||
return os << value.Value<VertexAccessor>();
|
return os << value.Value<VertexAccessor>();
|
||||||
case TypedValue::Type::Edge:
|
case TypedValue::Type::Edge:
|
||||||
return os << value.Value<EdgeAccessor>();
|
return os << value.Value<EdgeAccessor>();
|
||||||
case TypedValue::Type::Path:
|
case TypedValue::Type::Path:
|
||||||
return os << value.Value<Path>();
|
return os << value.Value<Path>();
|
||||||
}
|
}
|
||||||
permanent_fail("Unsupported PropertyValue::Type");
|
permanent_fail("Unsupported PropertyValue::Type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue& TypedValue::operator=(const TypedValue& other) {
|
TypedValue &TypedValue::operator=(const TypedValue &other) {
|
||||||
// set the type of this
|
// set the type of this
|
||||||
this->~TypedValue();
|
this->~TypedValue();
|
||||||
type_ = other.type_;
|
type_ = other.type_;
|
||||||
|
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
switch (other.type_) {
|
switch (other.type_) {
|
||||||
case TypedValue::Type::Null:
|
case TypedValue::Type::Null:
|
||||||
case TypedValue::Type::Bool:
|
case TypedValue::Type::Bool:
|
||||||
this->bool_v = other.bool_v;
|
this->bool_v = other.bool_v;
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::Int:
|
case TypedValue::Type::Int:
|
||||||
this->int_v = other.int_v;
|
this->int_v = other.int_v;
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::Double:
|
case TypedValue::Type::Double:
|
||||||
this->double_v = other.double_v;
|
this->double_v = other.double_v;
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::String:
|
case TypedValue::Type::String:
|
||||||
new (&string_v) std::string(other.string_v);
|
new (&string_v) std::string(other.string_v);
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::List:
|
case TypedValue::Type::List:
|
||||||
new (&list_v) std::vector<TypedValue>(other.list_v);
|
new (&list_v) std::vector<TypedValue>(other.list_v);
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::Map:
|
case TypedValue::Type::Map:
|
||||||
new (&map_v) std::map<std::string, TypedValue>(other.map_v);
|
new (&map_v) std::map<std::string, TypedValue>(other.map_v);
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::Vertex:
|
case TypedValue::Type::Vertex:
|
||||||
new (&vertex_v) VertexAccessor(other.vertex_v);
|
new (&vertex_v) VertexAccessor(other.vertex_v);
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::Edge:
|
case TypedValue::Type::Edge:
|
||||||
new (&edge_v) EdgeAccessor(other.edge_v);
|
new (&edge_v) EdgeAccessor(other.edge_v);
|
||||||
return *this;
|
return *this;
|
||||||
case TypedValue::Type::Path:
|
case TypedValue::Type::Path:
|
||||||
new (&path_v) Path(other.path_v);
|
new (&path_v) Path(other.path_v);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
permanent_fail("Unsupported TypedValue::Type");
|
permanent_fail("Unsupported TypedValue::Type");
|
||||||
@ -272,38 +332,38 @@ const TypedValue TypedValue::Null = TypedValue();
|
|||||||
|
|
||||||
TypedValue::~TypedValue() {
|
TypedValue::~TypedValue() {
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
// destructor for primitive types does nothing
|
// destructor for primitive types does nothing
|
||||||
case Type::Null:
|
case Type::Null:
|
||||||
case Type::Bool:
|
case Type::Bool:
|
||||||
case Type::Int:
|
case Type::Int:
|
||||||
case Type::Double:
|
case Type::Double:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// we need to call destructors for non primitive types since we used
|
// we need to call destructors for non primitive types since we used
|
||||||
// placement new
|
// placement new
|
||||||
case Type::String:
|
case Type::String:
|
||||||
// Clang fails to compile ~std::string. It seems it is a bug in some
|
// Clang fails to compile ~std::string. It seems it is a bug in some
|
||||||
// versions of clang. using namespace std statement solves the issue.
|
// versions of clang. using namespace std statement solves the issue.
|
||||||
using namespace std;
|
using namespace std;
|
||||||
string_v.~string();
|
string_v.~string();
|
||||||
return;
|
return;
|
||||||
case Type::List:
|
case Type::List:
|
||||||
using namespace std;
|
using namespace std;
|
||||||
list_v.~vector<TypedValue>();
|
list_v.~vector<TypedValue>();
|
||||||
return;
|
return;
|
||||||
case Type::Map:
|
case Type::Map:
|
||||||
using namespace std;
|
using namespace std;
|
||||||
map_v.~map<std::string, TypedValue>();
|
map_v.~map<std::string, TypedValue>();
|
||||||
return;
|
return;
|
||||||
case Type::Vertex:
|
case Type::Vertex:
|
||||||
vertex_v.~VertexAccessor();
|
vertex_v.~VertexAccessor();
|
||||||
return;
|
return;
|
||||||
case Type::Edge:
|
case Type::Edge:
|
||||||
edge_v.~EdgeAccessor();
|
edge_v.~EdgeAccessor();
|
||||||
return;
|
return;
|
||||||
case Type::Path:
|
case Type::Path:
|
||||||
path_v.~Path();
|
path_v.~Path();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
permanent_fail("Unsupported TypedValue::Type");
|
permanent_fail("Unsupported TypedValue::Type");
|
||||||
}
|
}
|
||||||
@ -315,19 +375,19 @@ TypedValue::~TypedValue() {
|
|||||||
* @param value
|
* @param value
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
double ToDouble(const TypedValue& value) {
|
double ToDouble(const TypedValue &value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case TypedValue::Type::Int:
|
case TypedValue::Type::Int:
|
||||||
return (double)value.Value<int64_t>();
|
return (double)value.Value<int64_t>();
|
||||||
case TypedValue::Type::Double:
|
case TypedValue::Type::Double:
|
||||||
return value.Value<double>();
|
return value.Value<double>();
|
||||||
default:
|
default:
|
||||||
throw TypedValueException(
|
throw TypedValueException(
|
||||||
"Unsupported TypedValue::Type conversion to double");
|
"Unsupported TypedValue::Type conversion to double");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator<(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator<(const TypedValue &a, const TypedValue &b) {
|
||||||
if (a.type() == TypedValue::Type::Bool || b.type() == TypedValue::Type::Bool)
|
if (a.type() == TypedValue::Type::Bool || b.type() == TypedValue::Type::Bool)
|
||||||
throw TypedValueException("Invalid 'less' operand types({} + {})", a.type(),
|
throw TypedValueException("Invalid 'less' operand types({} + {})", a.type(),
|
||||||
b.type());
|
b.type());
|
||||||
@ -356,7 +416,7 @@ TypedValue operator<(const TypedValue& a, const TypedValue& b) {
|
|||||||
|
|
||||||
// TODO: 2 = "2" -> false, I don't think this is handled correctly at the
|
// TODO: 2 = "2" -> false, I don't think this is handled correctly at the
|
||||||
// moment.
|
// moment.
|
||||||
TypedValue operator==(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator==(const TypedValue &a, const TypedValue &b) {
|
||||||
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
||||||
return TypedValue::Null;
|
return TypedValue::Null;
|
||||||
|
|
||||||
@ -370,7 +430,8 @@ TypedValue operator==(const TypedValue& a, const TypedValue& b) {
|
|||||||
// can compare list_v-s directly.
|
// can compare list_v-s directly.
|
||||||
auto list1 = a.Value<std::vector<TypedValue>>();
|
auto list1 = a.Value<std::vector<TypedValue>>();
|
||||||
auto list2 = b.Value<std::vector<TypedValue>>();
|
auto list2 = b.Value<std::vector<TypedValue>>();
|
||||||
if (list1.size() != list2.size()) return false;
|
if (list1.size() != list2.size())
|
||||||
|
return false;
|
||||||
for (int i = 0; i < (int)list1.size(); ++i) {
|
for (int i = 0; i < (int)list1.size(); ++i) {
|
||||||
if (!(list1[i] == list2[i]).Value<bool>()) {
|
if (!(list1[i] == list2[i]).Value<bool>()) {
|
||||||
return false;
|
return false;
|
||||||
@ -417,15 +478,15 @@ TypedValue operator==(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator!(const TypedValue& a) {
|
TypedValue operator!(const TypedValue &a) {
|
||||||
switch (a.type()) {
|
switch (a.type()) {
|
||||||
case TypedValue::Type::Null:
|
case TypedValue::Type::Null:
|
||||||
return TypedValue::Null;
|
return TypedValue::Null;
|
||||||
case TypedValue::Type::Bool:
|
case TypedValue::Type::Bool:
|
||||||
return TypedValue(!a.Value<bool>());
|
return TypedValue(!a.Value<bool>());
|
||||||
default:
|
default:
|
||||||
throw TypedValueException("Invalid logical not operand type (!{})",
|
throw TypedValueException("Invalid logical not operand type (!{})",
|
||||||
a.type());
|
a.type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,32 +496,32 @@ TypedValue operator!(const TypedValue& a) {
|
|||||||
* @param value a value.
|
* @param value a value.
|
||||||
* @return A string.
|
* @return A string.
|
||||||
*/
|
*/
|
||||||
std::string ValueToString(const TypedValue& value) {
|
std::string ValueToString(const TypedValue &value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case TypedValue::Type::String:
|
case TypedValue::Type::String:
|
||||||
return value.Value<std::string>();
|
return value.Value<std::string>();
|
||||||
case TypedValue::Type::Int:
|
case TypedValue::Type::Int:
|
||||||
return std::to_string(value.Value<int64_t>());
|
return std::to_string(value.Value<int64_t>());
|
||||||
case TypedValue::Type::Double:
|
case TypedValue::Type::Double:
|
||||||
return fmt::format("{}", value.Value<double>());
|
return fmt::format("{}", value.Value<double>());
|
||||||
// unsupported situations
|
// unsupported situations
|
||||||
default:
|
default:
|
||||||
throw TypedValueException(
|
throw TypedValueException(
|
||||||
"Unsupported TypedValue::Type conversion to string");
|
"Unsupported TypedValue::Type conversion to string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator-(const TypedValue& a) {
|
TypedValue operator-(const TypedValue &a) {
|
||||||
switch (a.type()) {
|
switch (a.type()) {
|
||||||
case TypedValue::Type::Null:
|
case TypedValue::Type::Null:
|
||||||
return TypedValue::Null;
|
return TypedValue::Null;
|
||||||
case TypedValue::Type::Int:
|
case TypedValue::Type::Int:
|
||||||
return -a.Value<int64_t>();
|
return -a.Value<int64_t>();
|
||||||
case TypedValue::Type::Double:
|
case TypedValue::Type::Double:
|
||||||
return -a.Value<double>();
|
return -a.Value<double>();
|
||||||
default:
|
default:
|
||||||
throw TypedValueException("Invalid unary minus operand type (-{})",
|
throw TypedValueException("Invalid unary minus operand type (-{})",
|
||||||
a.type());
|
a.type());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,13 +536,14 @@ TypedValue operator-(const TypedValue& a) {
|
|||||||
* @param op_name Name of the operation, used only for exception description,
|
* @param op_name Name of the operation, used only for exception description,
|
||||||
* if raised.
|
* if raised.
|
||||||
*/
|
*/
|
||||||
inline void EnsureArithmeticallyOk(const TypedValue& a, const TypedValue& b,
|
inline void EnsureArithmeticallyOk(const TypedValue &a, const TypedValue &b,
|
||||||
bool string_ok, const std::string& op_name) {
|
bool string_ok, const std::string &op_name) {
|
||||||
if (a.type() == TypedValue::Type::Bool || b.type() == TypedValue::Type::Bool)
|
if (a.type() == TypedValue::Type::Bool || b.type() == TypedValue::Type::Bool)
|
||||||
throw TypedValueException("Invalid {} operand types {}, {}", op_name,
|
throw TypedValueException("Invalid {} operand types {}, {}", op_name,
|
||||||
a.type(), b.type());
|
a.type(), b.type());
|
||||||
|
|
||||||
if (string_ok) return;
|
if (string_ok)
|
||||||
|
return;
|
||||||
|
|
||||||
if (a.type() == TypedValue::Type::String ||
|
if (a.type() == TypedValue::Type::String ||
|
||||||
b.type() == TypedValue::Type::String)
|
b.type() == TypedValue::Type::String)
|
||||||
@ -489,14 +551,14 @@ inline void EnsureArithmeticallyOk(const TypedValue& a, const TypedValue& b,
|
|||||||
a.type(), b.type());
|
a.type(), b.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator+(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator+(const TypedValue &a, const TypedValue &b) {
|
||||||
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
||||||
return TypedValue::Null;
|
return TypedValue::Null;
|
||||||
|
|
||||||
if (a.type() == TypedValue::Type::List ||
|
if (a.type() == TypedValue::Type::List ||
|
||||||
b.type() == TypedValue::Type::List) {
|
b.type() == TypedValue::Type::List) {
|
||||||
std::vector<TypedValue> list;
|
std::vector<TypedValue> list;
|
||||||
auto append_list = [&list](const TypedValue& v) {
|
auto append_list = [&list](const TypedValue &v) {
|
||||||
if (v.type() == TypedValue::Type::List) {
|
if (v.type() == TypedValue::Type::List) {
|
||||||
auto list2 = v.Value<std::vector<TypedValue>>();
|
auto list2 = v.Value<std::vector<TypedValue>>();
|
||||||
list.insert(list.end(), list2.begin(), list2.end());
|
list.insert(list.end(), list2.begin(), list2.end());
|
||||||
@ -525,7 +587,7 @@ TypedValue operator+(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator-(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator-(const TypedValue &a, const TypedValue &b) {
|
||||||
EnsureArithmeticallyOk(a, b, false, "subtraction");
|
EnsureArithmeticallyOk(a, b, false, "subtraction");
|
||||||
|
|
||||||
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
||||||
@ -540,7 +602,7 @@ TypedValue operator-(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator/(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator/(const TypedValue &a, const TypedValue &b) {
|
||||||
EnsureArithmeticallyOk(a, b, false, "division");
|
EnsureArithmeticallyOk(a, b, false, "division");
|
||||||
|
|
||||||
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
||||||
@ -555,7 +617,7 @@ TypedValue operator/(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator*(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator*(const TypedValue &a, const TypedValue &b) {
|
||||||
EnsureArithmeticallyOk(a, b, false, "multiplication");
|
EnsureArithmeticallyOk(a, b, false, "multiplication");
|
||||||
|
|
||||||
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
||||||
@ -570,7 +632,7 @@ TypedValue operator*(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator%(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator%(const TypedValue &a, const TypedValue &b) {
|
||||||
EnsureArithmeticallyOk(a, b, false, "modulo");
|
EnsureArithmeticallyOk(a, b, false, "modulo");
|
||||||
|
|
||||||
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
if (a.type() == TypedValue::Type::Null || b.type() == TypedValue::Type::Null)
|
||||||
@ -585,13 +647,13 @@ TypedValue operator%(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsLogicallyOk(const TypedValue& a) {
|
inline bool IsLogicallyOk(const TypedValue &a) {
|
||||||
return a.type() == TypedValue::Type::Bool ||
|
return a.type() == TypedValue::Type::Bool ||
|
||||||
a.type() == TypedValue::Type::Null;
|
a.type() == TypedValue::Type::Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Fix bugs in && and ||. null or true -> true; false and null -> false
|
// TODO: Fix bugs in && and ||. null or true -> true; false and null -> false
|
||||||
TypedValue operator&&(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator&&(const TypedValue &a, const TypedValue &b) {
|
||||||
if (IsLogicallyOk(a) && IsLogicallyOk(b)) {
|
if (IsLogicallyOk(a) && IsLogicallyOk(b)) {
|
||||||
if (a.type() == TypedValue::Type::Null ||
|
if (a.type() == TypedValue::Type::Null ||
|
||||||
b.type() == TypedValue::Type::Null) {
|
b.type() == TypedValue::Type::Null) {
|
||||||
@ -605,7 +667,7 @@ TypedValue operator&&(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator||(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator||(const TypedValue &a, const TypedValue &b) {
|
||||||
if (IsLogicallyOk(a) && IsLogicallyOk(b)) {
|
if (IsLogicallyOk(a) && IsLogicallyOk(b)) {
|
||||||
if (a.type() == TypedValue::Type::Null ||
|
if (a.type() == TypedValue::Type::Null ||
|
||||||
b.type() == TypedValue::Type::Null) {
|
b.type() == TypedValue::Type::Null) {
|
||||||
@ -619,7 +681,7 @@ TypedValue operator||(const TypedValue& a, const TypedValue& b) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedValue operator^(const TypedValue& a, const TypedValue& b) {
|
TypedValue operator^(const TypedValue &a, const TypedValue &b) {
|
||||||
if (IsLogicallyOk(a) && IsLogicallyOk(b)) {
|
if (IsLogicallyOk(a) && IsLogicallyOk(b)) {
|
||||||
if (a.type() == TypedValue::Type::Null ||
|
if (a.type() == TypedValue::Type::Null ||
|
||||||
b.type() == TypedValue::Type::Null) {
|
b.type() == TypedValue::Type::Null) {
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
|
#include "storage/edge_accessor.hpp"
|
||||||
|
#include "storage/property_value.hpp"
|
||||||
|
#include "storage/vertex_accessor.hpp"
|
||||||
|
#include "traversal/path.hpp"
|
||||||
#include "utils/exceptions/stacktrace_exception.hpp"
|
#include "utils/exceptions/stacktrace_exception.hpp"
|
||||||
#include "utils/total_ordering.hpp"
|
#include "utils/total_ordering.hpp"
|
||||||
#include "utils/underlying_cast.hpp"
|
#include "utils/underlying_cast.hpp"
|
||||||
#include "storage/property_value.hpp"
|
|
||||||
#include "storage/edge_accessor.hpp"
|
|
||||||
#include "storage/vertex_accessor.hpp"
|
|
||||||
#include "traversal/path.hpp"
|
|
||||||
|
|
||||||
typedef traversal_template::Path<VertexAccessor, EdgeAccessor> Path;
|
typedef traversal_template::Path<VertexAccessor, EdgeAccessor> Path;
|
||||||
|
|
||||||
@ -26,11 +26,11 @@ typedef traversal_template::Path<VertexAccessor, EdgeAccessor> Path;
|
|||||||
* TypedValue::Type. Each such type corresponds to exactly one C++ type.
|
* TypedValue::Type. Each such type corresponds to exactly one C++ type.
|
||||||
*/
|
*/
|
||||||
class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
||||||
public:
|
public:
|
||||||
/** Private default constructor, makes Null */
|
/** Private default constructor, makes Null */
|
||||||
TypedValue() : type_(Type::Null) {}
|
TypedValue() : type_(Type::Null) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** A value type. Each type corresponds to exactly one C++ type */
|
/** A value type. Each type corresponds to exactly one C++ type */
|
||||||
enum class Type : unsigned {
|
enum class Type : unsigned {
|
||||||
Null,
|
Null,
|
||||||
@ -58,32 +58,32 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
|||||||
operator PropertyValue() const;
|
operator PropertyValue() const;
|
||||||
|
|
||||||
/// constructors for non-primitive types
|
/// constructors for non-primitive types
|
||||||
TypedValue(const std::string& value) : type_(Type::String) {
|
TypedValue(const std::string &value) : type_(Type::String) {
|
||||||
new (&string_v) std::string(value);
|
new (&string_v) std::string(value);
|
||||||
}
|
}
|
||||||
TypedValue(const char* value) : type_(Type::String) {
|
TypedValue(const char *value) : type_(Type::String) {
|
||||||
new (&string_v) std::string(value);
|
new (&string_v) std::string(value);
|
||||||
}
|
}
|
||||||
TypedValue(const std::vector<TypedValue>& value) : type_(Type::List) {
|
TypedValue(const std::vector<TypedValue> &value) : type_(Type::List) {
|
||||||
new (&list_v) std::vector<TypedValue>(value);
|
new (&list_v) std::vector<TypedValue>(value);
|
||||||
}
|
}
|
||||||
TypedValue(const std::map<std::string, TypedValue>& value)
|
TypedValue(const std::map<std::string, TypedValue> &value)
|
||||||
: type_(Type::Map) {
|
: type_(Type::Map) {
|
||||||
new (&map_v) std::map<std::string, TypedValue>(value);
|
new (&map_v) std::map<std::string, TypedValue>(value);
|
||||||
}
|
}
|
||||||
TypedValue(const VertexAccessor& vertex) : type_(Type::Vertex) {
|
TypedValue(const VertexAccessor &vertex) : type_(Type::Vertex) {
|
||||||
new (&vertex_v) VertexAccessor(vertex);
|
new (&vertex_v) VertexAccessor(vertex);
|
||||||
}
|
}
|
||||||
TypedValue(const EdgeAccessor& edge) : type_(Type::Edge) {
|
TypedValue(const EdgeAccessor &edge) : type_(Type::Edge) {
|
||||||
new (&edge_v) EdgeAccessor(edge);
|
new (&edge_v) EdgeAccessor(edge);
|
||||||
}
|
}
|
||||||
TypedValue(const Path& path) : type_(Type::Path) { new (&path_v) Path(path); }
|
TypedValue(const Path &path) : type_(Type::Path) { new (&path_v) Path(path); }
|
||||||
TypedValue(const PropertyValue& value);
|
TypedValue(const PropertyValue &value);
|
||||||
|
|
||||||
// assignment ops
|
// assignment ops
|
||||||
TypedValue& operator=(const TypedValue& other);
|
TypedValue &operator=(const TypedValue &other);
|
||||||
|
|
||||||
TypedValue(const TypedValue& other);
|
TypedValue(const TypedValue &other);
|
||||||
~TypedValue();
|
~TypedValue();
|
||||||
|
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
@ -95,12 +95,12 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
|||||||
* @tparam T Type to interpret the value as.
|
* @tparam T Type to interpret the value as.
|
||||||
* @return The value as type T.
|
* @return The value as type T.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T> T &Value();
|
||||||
T Value() const;
|
template <typename T> const T &Value() const;
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& stream, const TypedValue&prop);
|
friend std::ostream &operator<<(std::ostream &stream, const TypedValue &prop);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// storage for the value of the property
|
// storage for the value of the property
|
||||||
union {
|
union {
|
||||||
bool bool_v;
|
bool bool_v;
|
||||||
@ -133,31 +133,31 @@ class TypedValue : public TotalOrdering<TypedValue, TypedValue, TypedValue> {
|
|||||||
* of incompatible Types.
|
* of incompatible Types.
|
||||||
*/
|
*/
|
||||||
class TypedValueException : public StacktraceException {
|
class TypedValueException : public StacktraceException {
|
||||||
public:
|
public:
|
||||||
using ::StacktraceException::StacktraceException;
|
using ::StacktraceException::StacktraceException;
|
||||||
};
|
};
|
||||||
|
|
||||||
// comparison operators
|
// comparison operators
|
||||||
// they return TypedValue because Null can be returned
|
// they return TypedValue because Null can be returned
|
||||||
TypedValue operator==(const TypedValue& a, const TypedValue& b);
|
TypedValue operator==(const TypedValue &a, const TypedValue &b);
|
||||||
TypedValue operator<(const TypedValue& a, const TypedValue& b);
|
TypedValue operator<(const TypedValue &a, const TypedValue &b);
|
||||||
TypedValue operator!(const TypedValue& a);
|
TypedValue operator!(const TypedValue &a);
|
||||||
|
|
||||||
// arithmetic operators
|
// arithmetic operators
|
||||||
TypedValue operator-(const TypedValue& a);
|
TypedValue operator-(const TypedValue &a);
|
||||||
TypedValue operator+(const TypedValue& a, const TypedValue& b);
|
TypedValue operator+(const TypedValue &a, const TypedValue &b);
|
||||||
TypedValue operator-(const TypedValue& a, const TypedValue& b);
|
TypedValue operator-(const TypedValue &a, const TypedValue &b);
|
||||||
TypedValue operator/(const TypedValue& a, const TypedValue& b);
|
TypedValue operator/(const TypedValue &a, const TypedValue &b);
|
||||||
TypedValue operator*(const TypedValue& a, const TypedValue& b);
|
TypedValue operator*(const TypedValue &a, const TypedValue &b);
|
||||||
TypedValue operator%(const TypedValue& a, const TypedValue& b);
|
TypedValue operator%(const TypedValue &a, const TypedValue &b);
|
||||||
|
|
||||||
// binary bool operators
|
// binary bool operators
|
||||||
TypedValue operator&&(const TypedValue& a, const TypedValue& b);
|
TypedValue operator&&(const TypedValue &a, const TypedValue &b);
|
||||||
TypedValue operator||(const TypedValue& a, const TypedValue& b);
|
TypedValue operator||(const TypedValue &a, const TypedValue &b);
|
||||||
// binary bool xor, not power operator
|
// binary bool xor, not power operator
|
||||||
// Be careful: since ^ is binary operator and || and && are logical operators
|
// Be careful: since ^ is binary operator and || and && are logical operators
|
||||||
// they have different priority in c++.
|
// they have different priority in c++.
|
||||||
TypedValue operator^(const TypedValue& a, const TypedValue& b);
|
TypedValue operator^(const TypedValue &a, const TypedValue &b);
|
||||||
|
|
||||||
// stream output
|
// stream output
|
||||||
std::ostream& operator<<(std::ostream& os, const TypedValue::Type type);
|
std::ostream &operator<<(std::ostream &os, const TypedValue::Type type);
|
||||||
|
Loading…
Reference in New Issue
Block a user