Add constraints on constructors
This commit is contained in:
parent
c96d8845be
commit
b180d8de00
|
@ -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)...) {}
|
||||||
|
|
|
@ -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>());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user