Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy any #4343

Merged
merged 11 commits into from
Jul 5, 2018
2 changes: 1 addition & 1 deletion src/shogun/base/SGObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class CSGObject
if (!has_parameter(tag))
return false;
const Any value = get_parameter(tag).get_value();
return value.same_type<T>();
return value.has_type<T>();
}

/** Setter for a class parameter, identified by a Tag.
Expand Down
167 changes: 91 additions & 76 deletions src/shogun/lib/any.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ namespace shogun
return compare_impl(maybe_most_important(), lhs, rhs);
}

template <class T>
bool compare_impl(maybe_most_important, const std::function<T()>& lhs, const std::function<T()>& rhs)
{
return compare(lhs(), rhs());
}

template <class T>
inline T clone_impl(general, T& value)
{
Expand Down Expand Up @@ -328,9 +334,26 @@ namespace shogun
template <class T>
inline const T& value_of(T const* ptr)
{
if (!ptr)
{
throw std::logic_error("Tried to access null pointer");
}
return *ptr;
}

template <class T>
const T& get_value(const void* storage)
{
return value_of(typed_pointer<T>(storage));
}

template <class T>
auto get_value(const void* storage) -> decltype(typed_pointer<T>(storage)())
{
return typed_pointer<T>(storage)();
}


template <class T, class S>
inline auto free_array(T* ptr, S size)
{
Expand Down Expand Up @@ -479,7 +502,7 @@ namespace shogun
* @param ti type information
* @return true if type matches
*/
virtual bool matches(const std::type_info& ti) const = 0;
virtual bool matches_type(const std::type_info& ti) const = 0;

/** Checks if policies are compatible.
* @param other other policy
Expand Down Expand Up @@ -508,18 +531,48 @@ namespace shogun
virtual void visit(void* storage, AnyVisitor* visitor) const = 0;
};

template <typename T>
class TypedAnyPolicy : public BaseAnyPolicy
{
public:
/** Returns type-name as string.
* @return name of type class
*/
virtual std::string type() const override
{
return demangled_type<T>();
}

/** Returns type info
* @return type info of value's type
*/
virtual const std::type_info& type_info() const override
{
return typeid(T);
}

/** Compares type.
* @param ti type information
* @return true if type matches
*/
virtual bool matches_type(const std::type_info& ti) const override
{
return typeid(T) == ti;
}
};

/** @brief This is one concrete implementation of policy that
* uses void pointers to store values.
*/
template <typename T>
class PointerValueAnyPolicy : public BaseAnyPolicy
class PointerValueAnyPolicy : public TypedAnyPolicy<T>
{
public:
/** Puts provided value pointed by v (untyped to be generic) to storage.
* @param storage pointer to a pointer to storage
* @param v pointer to value
*/
virtual void set(void** storage, const void* v) const
virtual void set(void** storage, const void* v) const override
{
*(storage) = new T(value_of(typed_pointer<T>(v)));
}
Expand All @@ -528,64 +581,39 @@ namespace shogun
* @param storage pointer to a pointer to storage
* @param from pointer to value to clone
*/
virtual void clone(void** storage, const void* from) const
virtual void clone(void** storage, const void* from) const override
{
any_detail::clone(storage, value_of(typed_pointer<T>(from)));
}

/** Clears storage.
* @param storage pointer to a pointer to storage
*/
virtual void clear(void** storage) const
virtual void clear(void** storage) const override
{
delete typed_pointer<T>(*storage);
}

/** Returns type-name as string.
* @return name of type class
*/
virtual std::string type() const
{
return demangled_type<T>();
}

/** Returns type info
* @return type info of value's type
*/
virtual const std::type_info& type_info() const
{
return typeid(T);
}

/** Compares type.
* @param ti type information
* @return true if type matches
*/
virtual bool matches(const std::type_info& ti) const
{
return typeid(T) == ti;
}

/** Checks if policies are compatible.
* @param other other policy
* @return true if policies do match
*/
virtual bool matches(BaseAnyPolicy* other) const;
virtual bool matches(BaseAnyPolicy* other) const override;

/** Compares two storages.
* @param storage pointer to a pointer to storage
* @param other_storage pointer to a pointer to another storage
* @return true if both storages have same value
*/
bool equals(const void* storage, const void* other_storage) const
bool equals(const void* storage, const void* other_storage) const override
{
const T& typed_storage = value_of(typed_pointer<T>(storage));
const T& typed_other_storage =
value_of(typed_pointer<T>(other_storage));
return compare(typed_storage, typed_other_storage);
}

virtual PolicyType policy_type() const
virtual PolicyType policy_type() const override
{
return PolicyType::OWNING;
}
Expand All @@ -595,21 +623,21 @@ namespace shogun
* @param storage pointer to a pointer to storage
* @param visitor abstract visitor to use
*/
virtual void visit(void* storage, AnyVisitor* visitor) const
virtual void visit(void* storage, AnyVisitor* visitor) const override
{
visitor->on(static_cast<T*>(storage));
}
};

template <typename T>
class NonOwningAnyPolicy : public BaseAnyPolicy
class NonOwningAnyPolicy : public TypedAnyPolicy<T>
{
public:
/** Puts provided value pointed by v (untyped to be generic) to storage.
* @param storage pointer to a pointer to storage
* @param v pointer to value
*/
virtual void set(void** storage, const void* v) const
virtual void set(void** storage, const void* v) const override
{
mutable_value_of<T>(storage) = value_of(typed_pointer<T>(v));
}
Expand All @@ -618,63 +646,38 @@ namespace shogun
* @param storage pointer to a pointer to storage
* @param from pointer to value to clone
*/
virtual void clone(void** storage, const void* from) const
virtual void clone(void** storage, const void* from) const override
{
any_detail::clone(storage, value_of(typed_pointer<T>(from)));
}

/** Clears storage.
* @param storage pointer to a pointer to storage
*/
virtual void clear(void** storage) const
{
}

/** Returns type-name as string.
* @return name of type class
*/
virtual std::string type() const
{
return demangled_type<T>();
}

/** Returns type info
* @return type info of value's type
*/
virtual const std::type_info& type_info() const
virtual void clear(void** storage) const override
{
return typeid(T);
}

/** Compares type.
* @param ti type information
* @return true if type matches
*/
virtual bool matches(const std::type_info& ti) const
{
return typeid(T) == ti;
}

/** Checks if policies are compatible.
* @param other other policy
* @return true if policies do match
*/
virtual bool matches(BaseAnyPolicy* other) const;
virtual bool matches(BaseAnyPolicy* other) const override;

/** Compares two storages.
* @param storage pointer to a pointer to storage
* @param other_storage pointer to a pointer to another storage
* @return true if both storages have same value
*/
bool equals(const void* storage, const void* other_storage) const
bool equals(const void* storage, const void* other_storage) const override
{
const T& typed_storage = value_of(typed_pointer<T>(storage));
const T& typed_other_storage =
value_of(typed_pointer<T>(other_storage));
return compare(typed_storage, typed_other_storage);
}

virtual PolicyType policy_type() const
virtual PolicyType policy_type() const override
{
return PolicyType::NON_OWNING;
}
Expand All @@ -684,7 +687,7 @@ namespace shogun
* @param storage pointer to storage
* @param visitor abstract visitor to use
*/
virtual void visit(void* storage, AnyVisitor* visitor) const
virtual void visit(void* storage, AnyVisitor* visitor) const override
{
visitor->on(static_cast<T*>(storage));
}
Expand Down Expand Up @@ -717,7 +720,7 @@ namespace shogun
{
return true;
}
return matches(other->type_info());
return this->matches_type(other->type_info());
}

template <class T>
Expand All @@ -731,7 +734,7 @@ namespace shogun
{
return true;
}
return matches(other->type_info());
return this->matches_type(other->type_info());
}

/** @brief Allows to store objects of arbitrary types
Expand Down Expand Up @@ -841,9 +844,9 @@ namespace shogun
template <typename T>
const T& as() const
{
if (same_type<T>())
if (has_type<T>())
{
return value_of(typed_pointer<T>(storage));
return any_detail::get_value<T>(storage);
}
else
{
Expand All @@ -854,24 +857,25 @@ namespace shogun

/** @return true if type is same. */
template <typename T>
inline bool same_type() const
inline bool has_type() const
{
return (policy == owning_policy<T>()) ||
(policy == non_owning_policy<T>()) ||
same_type_fallback<T>();
policy == owning_policy<std::function<T()>>() ||
has_type_fallback<T>();
}

/** @return true if type-id is same. */
template <typename T>
bool same_type_fallback() const
bool has_type_fallback() const
{
return policy->matches(typeid(T));
return policy->matches_type(typeid(T));
}

/** @return true if Any object is empty. */
bool empty() const
{
return same_type<Empty>();
return has_type<Empty>();
}

const std::type_info& type_info() const
Expand Down Expand Up @@ -948,6 +952,17 @@ namespace shogun
return Any(v);
}

/** Wraps a function as as instance of Any.
*
* @param func function to wrap
* @return Any object that uses the function to obtain its value
*/
template <typename T>
inline Any make_any(std::function<T()> func)
{
return Any(func);
}

template <typename T>
inline Any make_any_ref(T* v)
{
Expand Down