Add constraints on constructors

This commit is contained in:
Hosein Ghahramanzadeh 2019-08-14 21:03:17 +04:30
parent c96d8845be
commit b180d8de00
2 changed files with 86 additions and 12 deletions

View File

@ -1129,6 +1129,39 @@ struct Ignore {
Ignore(...); // NOLINT Ignore(...); // NOLINT
}; };
template <typename T>
struct TypeWrapper {
using type = T;
};
template <std::size_t, bool>
struct IndexedConditionalRedundantType {};
template <std::size_t I>
struct IndexedConditionalRedundantType<I, false> {
using type = void;
};
template <typename T, typename IndxSeq, bool... Cs>
struct EnableIfAllImpl;
template <typename T, std::size_t... Is, bool... Cs>
struct EnableIfAllImpl<T, IndexSequence<Is...>, Cs...>
: TypeWrapper<T>, IndexedConditionalRedundantType<Is, Cs>... {};
template <typename T = void, bool... Cs>
struct EnableIfAll
: EnableIfAllImpl<T, typename MakeIndexSequence<sizeof...(Cs)>::type,
Cs...> {};
template <std::size_t>
struct EmptyListElem {};
template <typename T>
struct ListElem {
using type = T;
};
template <typename> template <typename>
struct ElemFromListImpl; struct ElemFromListImpl;
template <size_t... I> template <size_t... I>
@ -1151,9 +1184,10 @@ struct ElemFromList {
template <typename T, std::size_t I> template <typename T, std::size_t I>
struct FlatTupleElem { struct FlatTupleElem {
T value; T value;
FlatTupleElem() : value() {} FlatTupleElem() noexcept(std::is_nothrow_constructible<T>::value) : value() {}
template <typename Arg> template <typename Arg, typename = typename EnableIfAll<
void, std::is_constructible<T, Arg>::value>::type>
explicit FlatTupleElem(Arg&& arg) : value(std::forward<Arg>(arg)) {} explicit FlatTupleElem(Arg&& arg) : value(std::forward<Arg>(arg)) {}
}; };
@ -1161,25 +1195,46 @@ template <typename IndexSeq, typename... Ts>
class FlatTupleBase; class FlatTupleBase;
template <std::size_t... Is, typename... Ts> template <std::size_t... Is, typename... Ts>
class FlatTupleBase<IndexSequence<Is...>, Ts...> class FlatTupleBase<IndexSequence<Is...>, Ts...> : FlatTupleElem<Ts, Is>... {
: FlatTupleElem<Ts, Is>... {
public: public:
FlatTupleBase() {} FlatTupleBase() {}
template <typename... Args> template <typename... Args,
typename = typename EnableIfAll<
void, sizeof...(Args) == sizeof...(Ts),
std::is_constructible<Ts, Args&&>::value...>::type>
explicit FlatTupleBase(Args&&... args) explicit FlatTupleBase(Args&&... args)
: FlatTupleElem<Ts, Is>(std::forward<Args>(args))... {} : FlatTupleElem<Ts, Is>(std::forward<Args>(args))... {}
template <typename... Args,
typename = typename EnableIfAll<
void, sizeof...(Args) == sizeof...(Ts),
std::is_constructible<Ts, Args>::value...>::type>
explicit FlatTupleBase(
const FlatTupleBase<IndexSequence<Is...>, Args...>& args_tuple)
: FlatTupleElem<Ts, Is>(args_tuple.template Get<Is>())... {}
template <typename... Args,
typename = typename EnableIfAll<
void, sizeof...(Args) == sizeof...(Ts),
std::is_constructible<Ts, Args>::value...>::type>
explicit FlatTupleBase(
FlatTupleBase<IndexSequence<Is...>, Args...>&& args_tuple)
: FlatTupleElem<Ts, Is>(args_tuple.template Get<Is>())... {}
template <std::size_t I> template <std::size_t I>
const typename ElemFromList<I, Ts...>::type& Get() const { const typename ElemFromList<I, Ts...>::type& Get() const {
return static_cast<const FlatTupleElem< return static_cast<
typename ElemFromList<I, Ts...>::type, I>*>(this)->value; const FlatTupleElem<typename ElemFromList<I, Ts...>::type, I>*>(
this)
->value;
} }
template <std::size_t I> template <std::size_t I>
typename ElemFromList<I, Ts...>::type& Get() { typename ElemFromList<I, Ts...>::type& Get() {
return static_cast<FlatTupleElem<typename ElemFromList<I, Ts...>::type, return static_cast<
I>*>(this)->value; FlatTupleElem<typename ElemFromList<I, Ts...>::type, I>*>(this)
->value;
} }
}; };
@ -1198,7 +1253,13 @@ struct FlatTuple
: FlatTupleBase<typename MakeIndexSequence<sizeof...(Ts)>::type, Ts...> { : FlatTupleBase<typename MakeIndexSequence<sizeof...(Ts)>::type, Ts...> {
FlatTuple() {} FlatTuple() {}
template <typename... Args> template <
typename... Args,
typename = typename EnableIfAll<
void, std::is_constructible<
FlatTupleBase<
typename MakeIndexSequence<sizeof...(Ts)>::type, Ts...>,
Args&&...>::value>::type>
explicit FlatTuple(Args&&... args) explicit FlatTuple(Args&&... args)
: FlatTupleBase<typename MakeIndexSequence<sizeof...(Ts)>::type, Ts...>( : FlatTupleBase<typename MakeIndexSequence<sizeof...(Ts)>::type, Ts...>(
std::forward<Args>(args)...) {} std::forward<Args>(args)...) {}

View File

@ -7368,6 +7368,9 @@ TEST(ElemFromList, Basic) {
TEST(FlatTuple, Basic) { TEST(FlatTuple, Basic) {
using testing::internal::FlatTuple; using testing::internal::FlatTuple;
EXPECT_TRUE(std::is_constructible<FlatTuple<>>::value);
EXPECT_TRUE((std::is_constructible<FlatTuple<>, FlatTuple<>>::value));
FlatTuple<int, double, const char*> tuple = {}; FlatTuple<int, double, const char*> tuple = {};
EXPECT_EQ(0, tuple.Get<0>()); EXPECT_EQ(0, tuple.Get<0>());
EXPECT_EQ(0.0, tuple.Get<1>()); EXPECT_EQ(0.0, tuple.Get<1>());
@ -7378,6 +7381,16 @@ TEST(FlatTuple, Basic) {
EXPECT_EQ(3.2, tuple.Get<1>()); EXPECT_EQ(3.2, tuple.Get<1>());
EXPECT_EQ(std::string("Foo"), tuple.Get<2>()); EXPECT_EQ(std::string("Foo"), tuple.Get<2>());
const FlatTuple<int, double, const char*> copy_constructed_tuple(tuple);
EXPECT_EQ(7, copy_constructed_tuple.Get<0>());
EXPECT_EQ(3.2, copy_constructed_tuple.Get<1>());
EXPECT_EQ(std::string("Foo"), copy_constructed_tuple.Get<2>());
FlatTuple<int, double, std::string> tuple_constructed_tuple(tuple);
EXPECT_EQ(7, tuple_constructed_tuple.Get<0>());
EXPECT_EQ(3.2, tuple_constructed_tuple.Get<1>());
EXPECT_EQ(std::string("Foo"), tuple_constructed_tuple.Get<2>());
tuple.Get<1>() = 5.1; tuple.Get<1>() = 5.1;
EXPECT_EQ(5.1, tuple.Get<1>()); EXPECT_EQ(5.1, tuple.Get<1>());
} }