Skip to content

Commit

Permalink
Pick Variant from Standalone Maybe (#6856)
Browse files Browse the repository at this point in the history
* refactor maybe: add variant

* maybe: add optional and tests

* maybe: add hash for optional & variant; support NullOpt for both optional & variant

* maybe: more notes

* maybe: binary search impl for Variant::Visit

* maybe: add more relational operator to optional & variant

* maybe: add nonstd::string_view

* maybe: fix construct of optional & variant

* maybe: support comparision for optional & variant

* maybe: add monadic operations for optional

* maybe: add error traits

* maybe: add JUST and Maybe

* maybe: remove useless comment

* maybe: add more test

* maybe: customizable JUST

* maybe: add Map and Bind (AndThen) to Maybe

* maybe: re-design JustConfig

* maybe: rename xxxT to xxxS

* maybe: fix method names

* maybe: add maybe to cmake

* maybe: fix error traits

* maybe: rename fields & add aggregate type checking

* maybe: move string_view to new file

* maybe: rename fields for optional and error

* maybe: new Value (no index checking, protected method) and Get (has check, public method)

* maybe: remove DefaultArgument

* Pick Variant from Standalone Maybe

Co-authored-by: oneflow-ci-bot <69100618+oneflow-ci-bot@users.noreply.github.com>
  • Loading branch information
PragmaTwice and oneflow-ci-bot committed Nov 29, 2021
1 parent 1f76768 commit 97e3ca0
Show file tree
Hide file tree
Showing 8 changed files with 1,086 additions and 3 deletions.
6 changes: 3 additions & 3 deletions cmake/oneflow.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ foreach(oneflow_single_file ${oneflow_all_src})
continue()
endif()

if("${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/(core|user|xrt)/.*\\.(h|hpp)$")
if("${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/(core|user|xrt|maybe)/.*\\.(h|hpp)$")
if((NOT RPC_BACKEND MATCHES "GRPC") AND "${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/core/control/.*")
# skip if GRPC not enabled
elseif(APPLE AND "${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/core/comm_network/(epoll|ibverbs)/.*")
Expand Down Expand Up @@ -228,8 +228,8 @@ foreach(oneflow_single_file ${oneflow_all_src})

endif(BUILD_PYTHON)

if("${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/(core|user|xrt)/.*\\.cpp$")
if("${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/(core|user|xrt)/.*_test\\.cpp$")
if("${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/(core|user|xrt|maybe)/.*\\.cpp$")
if("${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/(core|user|xrt|maybe)/.*_test\\.cpp$")
# test file
list(APPEND of_all_test_cc ${oneflow_single_file})
elseif(APPLE AND "${oneflow_single_file}" MATCHES "^${PROJECT_SOURCE_DIR}/oneflow/core/comm_network/(epoll|ibverbs)/.*")
Expand Down
52 changes: 52 additions & 0 deletions oneflow/maybe/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright 2020 The OneFlow Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef ONEFLOW_MAYBE_CONFIG_H_
#define ONEFLOW_MAYBE_CONFIG_H_

#include <cassert>

// pre-define it if you use a logging library like glog
#ifndef OF_MAYBE_ASSERT
#define OF_MAYBE_ASSERT(_cond_) assert(_cond_)
#endif

// ASSERT_EQ is different from ASSERT in logging / testing framework
// pre-define it if you use a logging library like glog
#ifndef OF_MAYBE_ASSERT_EQ
#define OF_MAYBE_ASSERT_EQ(_lhs_, _rhs_) OF_MAYBE_ASSERT(_lhs_ == _rhs_)
#endif

#if __GNUC__ >= 7
#define OF_MAYBE_HAS_IS_AGGREGATE
// in old versions of clang, __has_builtin(__is_aggregate) returns false
#elif __clang__
#if !__is_identifier(__is_aggregate)
#define OF_MAYBE_HAS_IS_AGGREGATE
#endif
#elif __has_builtin(__is_aggregate)
#define OF_MAYBE_HAS_IS_AGGREGATE
#endif

#ifdef OF_MAYBE_HAS_IS_AGGREGATE
#define OF_MAYBE_IS_AGGREGATE(...) __is_aggregate(__VA_ARGS__)
#else
// decay to POD checking if no such builtin (because implementing __is_aggregate need reflection)
#define OF_MAYBE_IS_AGGREGATE(...) \
std::is_standard_layout<__VA_ARGS__>::value&& std::is_trivial<__VA_ARGS__>::value
#endif

#endif // ONEFLOW_MAYBE_CONFIG_H_
152 changes: 152 additions & 0 deletions oneflow/maybe/type_traits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
Copyright 2020 The OneFlow Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef ONEFLOW_MAYBE_TYPE_TRAITS_H_
#define ONEFLOW_MAYBE_TYPE_TRAITS_H_

#include <cstddef>
#include <type_traits>
#include <tuple>
#include <utility>
#include "config.h"

namespace oneflow {

namespace maybe {

// in this file, xxxS represents struct of xxx
// for implementant aspect, xxx is an alias of xxxS::type or xxxS::value

template<bool B>
using BoolConstant = std::integral_constant<bool, B>;

template<std::size_t I>
using IndexConstant = std::integral_constant<std::size_t, I>;

constexpr std::size_t NPos = -1;

template<typename...>
struct ConjS : std::true_type {};
template<typename B1>
struct ConjS<B1> : B1 {};
template<typename B1, typename... Bn>
struct ConjS<B1, Bn...> : std::conditional_t<bool(B1::value), ConjS<Bn...>, B1> {};

template<typename... B>
constexpr bool Conj = ConjS<B...>::value;

template<typename...>
struct DisjS : std::false_type {};
template<typename B1>
struct DisjS<B1> : B1 {};
template<typename B1, typename... Bn>
struct DisjS<B1, Bn...> : std::conditional_t<bool(B1::value), B1, DisjS<Bn...>> {};

template<typename... B>
constexpr bool Disj = DisjS<B...>::value;

template<typename B>
struct NegS : BoolConstant<!bool(B::value)> {};

template<typename B>
constexpr bool Neg = NegS<B>::value;

struct TypeNotFound;

// return TypeNotFound while out of range
template<std::size_t I, typename... Tn>
struct TypeGetS;

template<std::size_t I, typename T1, typename... Tn>
struct TypeGetS<I, T1, Tn...> : TypeGetS<I - 1, Tn...> {};

template<typename T1, typename... Tn>
struct TypeGetS<0, T1, Tn...> {
using type = T1;
};

template<std::size_t N>
struct TypeGetS<N> {
using type = TypeNotFound;
};

template<std::size_t I, typename... Ts>
using TypeGet = typename TypeGetS<I, Ts...>::type;

// return NPos (-1) while not found
template<std::size_t I, typename T, typename... Tn>
struct IndexGetFromS;

template<std::size_t I, typename T, typename T1, typename... Tn>
struct IndexGetFromS<I, T, T1, Tn...> : IndexGetFromS<I + 1, T, Tn...> {};

template<std::size_t I, typename T1, typename... Tn>
struct IndexGetFromS<I, T1, T1, Tn...> : IndexConstant<I> {};

template<std::size_t I, typename T>
struct IndexGetFromS<I, T> : IndexConstant<NPos> {};

template<typename T, typename... Ts>
constexpr auto IndexGet = IndexGetFromS<0, T, Ts...>::value;

template<typename T, typename... Ts>
constexpr auto TypeIn = IndexGet<T, Ts...> != NPos;

template<typename T, typename... Ts>
using TypeInS = BoolConstant<TypeIn<T, Ts...>>;

template<typename T>
struct RemoveCVRefS {
using type = std::remove_cv_t<std::remove_reference_t<T>>;
};

template<typename T>
using RemoveCVRef = typename RemoveCVRefS<T>::type;

template<typename T, typename... Ts>
struct IsDifferentTypesS : BoolConstant<!TypeIn<T, Ts...> && IsDifferentTypesS<Ts...>::value> {};

template<typename T>
struct IsDifferentTypesS<T> : std::true_type {};

template<typename T, typename... Ts>
constexpr auto IsDifferentTypes = IsDifferentTypesS<T, Ts...>::value;

template<typename T>
struct ConstRefExceptVoidS {
using type = const T&;
};

template<>
struct ConstRefExceptVoidS<void> {
using type = void;
};

template<typename T>
using ConstRefExceptVoid = typename ConstRefExceptVoidS<T>::type;

template<typename T>
using RemoveRValRef =
std::conditional_t<std::is_rvalue_reference<T>::value, std::remove_reference_t<T>, T>;

template<typename T>
constexpr bool IsAggregate = OF_MAYBE_IS_AGGREGATE(T);

} // namespace maybe

} // namespace oneflow

#endif // ONEFLOW_MAYBE_TYPE_TRAITS_H_
64 changes: 64 additions & 0 deletions oneflow/maybe/type_traits_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright 2020 The OneFlow Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <gtest/gtest.h>
#include <type_traits>
#include "oneflow/maybe/type_traits.h"

using namespace oneflow::maybe;

TEST(TypeTraits, Basics) {
static_assert(Conj<std::true_type, std::true_type>, "");
static_assert(!Conj<std::false_type, std::true_type>, "");
static_assert(!Conj<std::true_type, std::false_type>, "");
static_assert(!Conj<std::false_type, std::false_type>, "");
static_assert(!Conj<std::true_type, std::true_type, std::false_type>, "");

static_assert(Disj<std::true_type, std::true_type>, "");
static_assert(Disj<std::false_type, std::true_type>, "");
static_assert(Disj<std::true_type, std::false_type>, "");
static_assert(!Disj<std::false_type, std::false_type>, "");
static_assert(Disj<std::true_type, std::true_type, std::false_type>, "");
static_assert(!Disj<std::false_type, std::false_type, std::false_type>, "");

static_assert(std::is_same<TypeGet<0, int>, int>::value, "");
static_assert(std::is_same<TypeGet<0, int, float>, int>::value, "");
static_assert(std::is_same<TypeGet<1, int, float>, float>::value, "");
static_assert(std::is_same<TypeGet<2, int, float, bool, int>, bool>::value, "");
static_assert(std::is_same<TypeGet<2, int, int>, TypeNotFound>::value, "");
static_assert(std::is_same<TypeGet<2, int, int, float>, float>::value, "");
static_assert(std::is_same<TypeGet<2, int, int, float, int>, float>::value, "");
static_assert(std::is_same<TypeGet<2>, TypeNotFound>::value, "");

static_assert(IndexGet<int, int> == 0, "");
static_assert(IndexGet<int, float> == NPos, "");
static_assert(IndexGet<int, int, int> == 0, "");
static_assert(IndexGet<int, float, int> == 1, "");
static_assert(IndexGet<bool, int, float, int, bool, bool, int> == 3, "");
static_assert(IndexGet<int> == NPos, "");

static_assert(!TypeIn<int>, "");
static_assert(TypeIn<int, int>, "");
static_assert(TypeIn<int, float, int>, "");
static_assert(!TypeIn<int, float, float, bool>, "");
static_assert(TypeIn<int, float, bool, int, float>, "");
static_assert(TypeIn<bool, float, float, bool>, "");

static_assert(IsDifferentTypes<int, float, bool>, "");
static_assert(!IsDifferentTypes<int, float, int, bool>, "");
static_assert(IsDifferentTypes<int>, "");
static_assert(!IsDifferentTypes<int, int>, "");
}
89 changes: 89 additions & 0 deletions oneflow/maybe/utility.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright 2020 The OneFlow Authors. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef ONEFLOW_MAYBE_UTILITY_H_
#define ONEFLOW_MAYBE_UTILITY_H_

#include <cstddef>
#include <functional>

namespace oneflow {

namespace maybe {

// unlike std::nullopt in c++17, the NullOptType is used in both Variant and Optional,
// so it is more like both std::nullopt and std::monostate (in c++17),
// the advantage of this unification is a more unifed experience,
// i.e. `return NullOpt` can be used in both Variant and Optional context
struct NullOptType {
explicit constexpr NullOptType() = default;

bool operator==(NullOptType) const { return true; }
bool operator!=(NullOptType) const { return false; }
bool operator<(NullOptType) const { return false; }
bool operator>(NullOptType) const { return false; }
bool operator<=(NullOptType) const { return true; }
bool operator>=(NullOptType) const { return true; }
};

constexpr const std::size_t NullOptHash = -3333;

constexpr NullOptType NullOpt{};

struct InPlaceT {
explicit constexpr InPlaceT() = default;
};

constexpr InPlaceT InPlace;

template<typename T>
struct InPlaceTypeT {
explicit constexpr InPlaceTypeT() = default;
};

template<typename T>
constexpr InPlaceTypeT<T> InPlaceType;

template<std::size_t I>
struct InPlaceIndexT {
explicit constexpr InPlaceIndexT() = default;
};

template<std::size_t I>
constexpr InPlaceIndexT<I> InPlaceIndex;

template<class T>
constexpr void HashCombine(std::size_t& seed, const T& v) {
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

} // namespace maybe

} // namespace oneflow

namespace std {

template<>
struct hash<oneflow::maybe::NullOptType> {
size_t operator()(oneflow::maybe::NullOptType) const noexcept {
return oneflow::maybe::NullOptHash;
}
};

} // namespace std

#endif // ONEFLOW_MAYBE_UTILITY_H_
Loading

0 comments on commit 97e3ca0

Please sign in to comment.