-
Notifications
You must be signed in to change notification settings - Fork 664
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pick Variant from Standalone Maybe (#6856)
* 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
1 parent
1f76768
commit 97e3ca0
Showing
8 changed files
with
1,086 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>, ""); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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_ |
Oops, something went wrong.