Skip to content

Commit

Permalink
Support equals in operator== of Any (#4056)
Browse files Browse the repository at this point in the history
- REQUIRE C++14 FROM NOW ON
  • Loading branch information
lisitsyn committed Dec 28, 2017
1 parent 8715787 commit 69c4702
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 10 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -32,7 +32,7 @@ include(ShogunUtils)
SET(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)

#### set required C++ standard level of the compiler
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (MSVC)
Expand Down
4 changes: 2 additions & 2 deletions src/shogun/lib/SGVector.cpp
Expand Up @@ -391,8 +391,8 @@ void SGVector<T>::free_data()
gpu_ptr=NULL;
}

template<class T>
bool SGVector<T>::equals(SGVector<T>& other)
template <class T>
bool SGVector<T>::equals(SGVector<T>& other) const
{
assert_on_cpu();
if (other.vlen!=vlen)
Expand Down
2 changes: 1 addition & 1 deletion src/shogun/lib/SGVector.h
Expand Up @@ -368,7 +368,7 @@ template<class T> class SGVector : public SGReferencedData
* @return false if any element differs or if sizes are different,
* true otherwise
*/
bool equals(SGVector<T>& other);
bool equals(SGVector<T>& other) const;

/// || x ||_2
static T twonorm(const T* x, int32_t len);
Expand Down
62 changes: 56 additions & 6 deletions src/shogun/lib/any.h
Expand Up @@ -71,6 +71,56 @@ namespace shogun
NON_OWNING
};

namespace any_detail
{

struct by_default
{
};

struct general : by_default
{
};

struct more_important : general
{
};

struct maybe_most_important : more_important
{
};

template <class T>
auto compare_impl(by_default, T& lhs, T& rhs) = delete;

template <class T>
auto compare_impl(general, T& lhs, T& rhs) -> decltype(lhs == rhs)
{
return lhs == rhs;
}

template <class T>
auto compare_impl(more_important, T& lhs, T& rhs)
-> decltype(lhs.equals(rhs))
{
return lhs.equals(rhs);
}

template <class T>
auto compare_impl(maybe_most_important, T* lhs, T* rhs)
-> decltype(lhs->equals(rhs))
{
return lhs->equals(rhs);
}

template <class T>
auto compare(T& lhs, T& rhs)
-> decltype(compare_impl(maybe_most_important(), lhs, rhs))
{
return compare_impl(maybe_most_important(), lhs, rhs);
}
}

/** @brief An interface for a policy to store a value.
* Value can be any data like primitive data-types, shogun objects, etc.
* Policy defines how to handle this data. It works with a
Expand Down Expand Up @@ -188,9 +238,9 @@ namespace shogun
*/
bool equals(void** storage, void** other_storage) const
{
T typed_storage = *(reinterpret_cast<T*>(*storage));
T typed_other_storage = *(reinterpret_cast<T*>(*other_storage));
return typed_storage == typed_other_storage;
T& typed_storage = *(reinterpret_cast<T*>(*storage));
T& typed_other_storage = *(reinterpret_cast<T*>(*other_storage));
return any_detail::compare(typed_storage, typed_other_storage);
}

virtual PolicyType policy_type() const
Expand Down Expand Up @@ -257,9 +307,9 @@ namespace shogun
*/
bool equals(void** storage, void** other_storage) const
{
T typed_storage = *(reinterpret_cast<T*>(*storage));
T typed_other_storage = *(reinterpret_cast<T*>(*other_storage));
return typed_storage == typed_other_storage;
T& typed_storage = *(reinterpret_cast<T*>(*storage));
T& typed_other_storage = *(reinterpret_cast<T*>(*other_storage));
return any_detail::compare(typed_storage, typed_other_storage);
}

virtual PolicyType policy_type() const
Expand Down
39 changes: 39 additions & 0 deletions tests/unit/lib/Any_unittest.cc
Expand Up @@ -37,6 +37,19 @@

using namespace shogun;

struct Simple
{
public:
bool equals(const Simple* other) const
{
return true;
}
bool equals(const Simple& other) const
{
return true;
}
};

TEST(Any, as)
{
int32_t integer = 10;
Expand Down Expand Up @@ -253,3 +266,29 @@ TEST(Any, store_non_owning_in_map)
integer = 13;
EXPECT_EQ(map.at("something").as<int32_t>(), integer);
}

TEST(Any, equals_int)
{
int32_t a = 1;
int32_t b = 1;
EXPECT_EQ(erase_type(a), erase_type(b));
EXPECT_EQ(erase_type(b), erase_type(a));
}

TEST(Any, equals_pointer)
{
Simple* a = new Simple;
Simple* b = new Simple;
EXPECT_EQ(erase_type(a), erase_type(b));
EXPECT_EQ(erase_type(b), erase_type(a));
delete a;
delete b;
}

TEST(Any, equals_value)
{
Simple a;
Simple b;
EXPECT_EQ(erase_type(a), erase_type(b));
EXPECT_EQ(erase_type(b), erase_type(a));
}

0 comments on commit 69c4702

Please sign in to comment.