Add constraints on constructors
This commit is contained in:
parent
c96d8845be
commit
b180d8de00
|
@ -1129,6 +1129,39 @@ struct Ignore {
|
|||
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>
|
||||
struct ElemFromListImpl;
|
||||
template <size_t... I>
|
||||
|
@ -1151,35 +1184,57 @@ struct ElemFromList {
|
|||
template <typename T, std::size_t I>
|
||||
struct FlatTupleElem {
|
||||
T value;
|
||||
FlatTupleElem() : value() {}
|
||||
FlatTupleElem() noexcept(std::is_nothrow_constructible<T>::value) : value() {}
|
||||
|
||||
template <typename Arg>
|
||||
explicit FlatTupleElem(Arg &&arg) : value(std::forward<Arg>(arg)) {}
|
||||
template <typename Arg, typename = typename EnableIfAll<
|
||||
void, std::is_constructible<T, Arg>::value>::type>
|
||||
explicit FlatTupleElem(Arg&& arg) : value(std::forward<Arg>(arg)) {}
|
||||
};
|
||||
|
||||
template <typename IndexSeq, typename... Ts>
|
||||
class FlatTupleBase;
|
||||
|
||||
template <std::size_t... Is, typename... Ts>
|
||||
class FlatTupleBase<IndexSequence<Is...>, Ts...>
|
||||
: FlatTupleElem<Ts, Is>... {
|
||||
class FlatTupleBase<IndexSequence<Is...>, Ts...> : FlatTupleElem<Ts, Is>... {
|
||||
public:
|
||||
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)
|
||||
: 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>
|
||||
const typename ElemFromList<I, Ts...>::type& Get() const {
|
||||
return static_cast<const FlatTupleElem<
|
||||
typename ElemFromList<I, Ts...>::type, I>*>(this)->value;
|
||||
return static_cast<
|
||||
const FlatTupleElem<typename ElemFromList<I, Ts...>::type, I>*>(
|
||||
this)
|
||||
->value;
|
||||
}
|
||||
|
||||
template <std::size_t I>
|
||||
typename ElemFromList<I, Ts...>::type& Get() {
|
||||
return static_cast<FlatTupleElem<typename ElemFromList<I, Ts...>::type,
|
||||
I>*>(this)->value;
|
||||
return static_cast<
|
||||
FlatTupleElem<typename ElemFromList<I, Ts...>::type, I>*>(this)
|
||||
->value;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1198,10 +1253,16 @@ struct FlatTuple
|
|||
: FlatTupleBase<typename MakeIndexSequence<sizeof...(Ts)>::type, Ts...> {
|
||||
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)
|
||||
: FlatTupleBase<typename MakeIndexSequence<sizeof...(Ts)>::type, Ts...>(
|
||||
std::forward<Args>(args)...){}
|
||||
std::forward<Args>(args)...) {}
|
||||
};
|
||||
|
||||
// Utility functions to be called with static_assert to induce deprecation
|
||||
|
|
|
@ -7368,6 +7368,9 @@ TEST(ElemFromList, Basic) {
|
|||
TEST(FlatTuple, Basic) {
|
||||
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 = {};
|
||||
EXPECT_EQ(0, tuple.Get<0>());
|
||||
EXPECT_EQ(0.0, tuple.Get<1>());
|
||||
|
@ -7378,6 +7381,16 @@ TEST(FlatTuple, Basic) {
|
|||
EXPECT_EQ(3.2, tuple.Get<1>());
|
||||
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;
|
||||
EXPECT_EQ(5.1, tuple.Get<1>());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user