Skip to content

Commit 1382500

Browse files
kghostpull[bot]
authored andcommitted
Variant: Remove requriment of VariantId (#9313)
1 parent 1c6b9e6 commit 1382500

File tree

4 files changed

+97
-49
lines changed

4 files changed

+97
-49
lines changed

src/app/util/af-types.h

-8
Original file line numberDiff line numberDiff line change
@@ -1297,50 +1297,42 @@ class MessageSendDestination
12971297
private:
12981298
struct VariantViaBinding
12991299
{
1300-
static constexpr const std::size_t VariantId = 1;
13011300
explicit VariantViaBinding(uint8_t bindingIndex) : mBindingIndex(bindingIndex) {}
13021301
uint8_t mBindingIndex;
13031302
};
13041303

13051304
struct VariantViaAddressTable
13061305
{
1307-
static constexpr const std::size_t VariantId = 2;
13081306
};
13091307

13101308
struct VariantDirect
13111309
{
1312-
static constexpr const std::size_t VariantId = 3;
13131310
explicit VariantDirect(NodeId nodeId) : mNodeId(nodeId) {}
13141311
NodeId mNodeId;
13151312
};
13161313

13171314
struct VariantMulticast
13181315
{
1319-
static constexpr const std::size_t VariantId = 4;
13201316
explicit VariantMulticast(GroupId groupId) : mGroupId(groupId) {}
13211317
GroupId mGroupId;
13221318
};
13231319

13241320
struct VariantMulticastWithAlias
13251321
{
1326-
static constexpr const std::size_t VariantId = 5;
13271322
explicit VariantMulticastWithAlias(GroupId groupId) : mGroupId(groupId) {}
13281323
GroupId mGroupId;
13291324
};
13301325

13311326
struct VariantBroadcast
13321327
{
1333-
static constexpr const std::size_t VariantId = 6;
13341328
};
13351329

13361330
struct VariantBroadcastWithAlias
13371331
{
1338-
static constexpr const std::size_t VariantId = 7;
13391332
};
13401333

13411334
struct VariantViaExchange
13421335
{
1343-
static constexpr const std::size_t VariantId = 8;
13441336
explicit VariantViaExchange(Messaging::ExchangeContext * exchangeContext) : mExchangeContext(exchangeContext) {}
13451337
Messaging::ExchangeContext * mExchangeContext;
13461338
};

src/channel/ChannelContext.h

-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ class ChannelContext : public ReferenceCounted<ChannelContext, ChannelContextDel
136136
// mPreparing is pretty big, consider move it outside
137137
struct PrepareVars
138138
{
139-
static constexpr const size_t VariantId = 1;
140139
PrepareState mState;
141140
Inet::IPAddressType mAddressType;
142141
Inet::IPAddress mAddress;
@@ -146,7 +145,6 @@ class ChannelContext : public ReferenceCounted<ChannelContext, ChannelContextDel
146145

147146
struct ReadyVars
148147
{
149-
static constexpr const size_t VariantId = 2;
150148
ReadyVars(SessionHandle session) : mSession(session) {}
151149
const SessionHandle mSession;
152150
};

src/lib/support/Variant.h

+46-28
Original file line numberDiff line numberDiff line change
@@ -30,55 +30,55 @@ namespace chip {
3030

3131
namespace VariantInternal {
3232

33-
template <typename... Ts>
33+
template <std::size_t Index, typename... Ts>
3434
struct VariantCurry;
3535

36-
template <typename T, typename... Ts>
37-
struct VariantCurry<T, Ts...>
36+
template <std::size_t Index, typename T, typename... Ts>
37+
struct VariantCurry<Index, T, Ts...>
3838
{
3939
inline static void Destroy(std::size_t id, void * data)
4040
{
41-
if (id == T::VariantId)
41+
if (id == Index)
4242
reinterpret_cast<T *>(data)->~T();
4343
else
44-
VariantCurry<Ts...>::Destroy(id, data);
44+
VariantCurry<Index + 1, Ts...>::Destroy(id, data);
4545
}
4646

4747
inline static void Move(std::size_t that_t, void * that_v, void * this_v)
4848
{
49-
if (that_t == T::VariantId)
49+
if (that_t == Index)
5050
new (this_v) T(std::move(*reinterpret_cast<T *>(that_v)));
5151
else
52-
VariantCurry<Ts...>::Move(that_t, that_v, this_v);
52+
VariantCurry<Index + 1, Ts...>::Move(that_t, that_v, this_v);
5353
}
5454

5555
inline static void Copy(std::size_t that_t, const void * that_v, void * this_v)
5656
{
57-
if (that_t == T::VariantId)
57+
if (that_t == Index)
5858
{
5959
new (this_v) T(*reinterpret_cast<const T *>(that_v));
6060
}
6161
else
6262
{
63-
VariantCurry<Ts...>::Copy(that_t, that_v, this_v);
63+
VariantCurry<Index + 1, Ts...>::Copy(that_t, that_v, this_v);
6464
}
6565
}
6666

6767
inline static bool Equal(std::size_t type_t, const void * that_v, const void * this_v)
6868
{
69-
if (type_t == T::VariantId)
69+
if (type_t == Index)
7070
{
7171
return *reinterpret_cast<const T *>(this_v) == *reinterpret_cast<const T *>(that_v);
7272
}
7373
else
7474
{
75-
return VariantCurry<Ts...>::Equal(type_t, that_v, this_v);
75+
return VariantCurry<Index + 1, Ts...>::Equal(type_t, that_v, this_v);
7676
}
7777
}
7878
};
7979

80-
template <>
81-
struct VariantCurry<>
80+
template <std::size_t Index>
81+
struct VariantCurry<Index>
8282
{
8383
inline static void Destroy(std::size_t id, void * data) {}
8484
inline static void Move(std::size_t that_t, void * that_v, void * this_v) {}
@@ -90,23 +90,41 @@ struct VariantCurry<>
9090
}
9191
};
9292

93+
template <typename T, typename TupleType>
94+
class TupleIndexOfType
95+
{
96+
private:
97+
template <std::size_t Index>
98+
static constexpr
99+
typename std::enable_if<std::is_same<T, typename std::tuple_element<Index, TupleType>::type>::value, std::size_t>::type
100+
calculate()
101+
{
102+
return Index;
103+
}
104+
105+
template <std::size_t Index>
106+
static constexpr
107+
typename std::enable_if<!std::is_same<T, typename std::tuple_element<Index, TupleType>::type>::value, std::size_t>::type
108+
calculate()
109+
{
110+
return calculate<Index + 1>();
111+
}
112+
113+
public:
114+
static constexpr std::size_t value = calculate<0>();
115+
};
116+
93117
} // namespace VariantInternal
94118

95119
/**
96120
* @brief
97121
* Represents a type-safe union. An instance of Variant at any given time either holds a value of one of its
98-
* alternative types, or no value. Each type must define a unique value of a static field named VariantId.
122+
* alternative types, or no value.
99123
*
100124
* Example:
101-
* struct Type1
102-
* {
103-
* static constexpr const std::size_t VariantId = 1;
104-
* };
125+
* struct Type1 {};
105126
*
106-
* struct Type2
107-
* {
108-
* static constexpr const std::size_t VariantId = 2;
109-
* };
127+
* struct Type2 {};
110128
*
111129
* Variant<Type1, Type2> v;
112130
* v.Set<Type1>(); // v contains Type1
@@ -121,7 +139,7 @@ struct Variant
121139
static constexpr std::size_t kInvalidType = SIZE_MAX;
122140

123141
using Data = typename std::aligned_storage<kDataSize, kDataAlign>::type;
124-
using Curry = VariantInternal::VariantCurry<Ts...>;
142+
using Curry = VariantInternal::VariantCurry<0, Ts...>;
125143

126144
std::size_t mTypeId;
127145
Data mData;
@@ -158,13 +176,13 @@ struct Variant
158176

159177
bool operator==(const Variant & other) const
160178
{
161-
return GetType() == other.GetType() && Curry::Equal(mTypeId, &other.mData, &mData);
179+
return GetType() == other.GetType() && (!Valid() || Curry::Equal(mTypeId, &other.mData, &mData));
162180
}
163181

164182
template <typename T>
165183
bool Is() const
166184
{
167-
return (mTypeId == T::VariantId);
185+
return (mTypeId == VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value);
168186
}
169187

170188
std::size_t GetType() const { return mTypeId; }
@@ -176,20 +194,20 @@ struct Variant
176194
{
177195
Curry::Destroy(mTypeId, &mData);
178196
new (&mData) T(std::forward<Args>(args)...);
179-
mTypeId = T::VariantId;
197+
mTypeId = VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value;
180198
}
181199

182200
template <typename T>
183201
T & Get()
184202
{
185-
VerifyOrDie(mTypeId == T::VariantId);
203+
VerifyOrDie((mTypeId == VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value));
186204
return *reinterpret_cast<T *>(&mData);
187205
}
188206

189207
template <typename T>
190208
const T & Get() const
191209
{
192-
VerifyOrDie(mTypeId == T::VariantId);
210+
VerifyOrDie((mTypeId == VariantInternal::TupleIndexOfType<T, std::tuple<Ts...>>::value));
193211
return *reinterpret_cast<const T *>(&mData);
194212
}
195213

src/lib/support/tests/TestVariant.cpp

+51-11
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,20 @@ namespace {
2525

2626
struct Simple
2727
{
28-
static constexpr const std::size_t VariantId = 1;
28+
bool operator==(const Simple &) const { return true; }
2929
};
3030

3131
struct Pod
3232
{
33-
static constexpr const std::size_t VariantId = 2;
34-
3533
Pod(int v1, int v2) : m1(v1), m2(v2) {}
34+
bool operator==(const Pod & other) const { return m1 == other.m1 && m2 == other.m2; }
3635

3736
int m1;
3837
int m2;
3938
};
4039

4140
struct Movable
4241
{
43-
static constexpr const std::size_t VariantId = 3;
44-
4542
Movable(int v1, int v2) : m1(v1), m2(v2) {}
4643

4744
Movable(Movable &) = delete;
@@ -56,8 +53,6 @@ struct Movable
5653

5754
struct Count
5855
{
59-
static constexpr const std::size_t VariantId = 4;
60-
6156
Count() { ++created; }
6257
~Count() { ++destroyed; }
6358

@@ -213,6 +208,50 @@ void TestVariantMoveAssign(nlTestSuite * inSuite, void * inContext)
213208
NL_TEST_ASSERT(inSuite, v2.Get<Pod>().m2 == 10);
214209
}
215210

211+
void TestVariantCompare(nlTestSuite * inSuite, void * inContext)
212+
{
213+
Variant<Simple, Pod> v0;
214+
Variant<Simple, Pod> v1;
215+
Variant<Simple, Pod> v2;
216+
Variant<Simple, Pod> v3;
217+
Variant<Simple, Pod> v4;
218+
219+
v1.Set<Simple>();
220+
v2.Set<Pod>(5, 10);
221+
v3.Set<Pod>(5, 10);
222+
v4.Set<Pod>(5, 11);
223+
224+
NL_TEST_ASSERT(inSuite, (v0 == v0));
225+
NL_TEST_ASSERT(inSuite, !(v0 == v1));
226+
NL_TEST_ASSERT(inSuite, !(v0 == v2));
227+
NL_TEST_ASSERT(inSuite, !(v0 == v3));
228+
NL_TEST_ASSERT(inSuite, !(v0 == v4));
229+
230+
NL_TEST_ASSERT(inSuite, !(v1 == v0));
231+
NL_TEST_ASSERT(inSuite, (v1 == v1));
232+
NL_TEST_ASSERT(inSuite, !(v1 == v2));
233+
NL_TEST_ASSERT(inSuite, !(v1 == v3));
234+
NL_TEST_ASSERT(inSuite, !(v1 == v4));
235+
236+
NL_TEST_ASSERT(inSuite, !(v2 == v0));
237+
NL_TEST_ASSERT(inSuite, !(v2 == v1));
238+
NL_TEST_ASSERT(inSuite, (v2 == v2));
239+
NL_TEST_ASSERT(inSuite, (v2 == v3));
240+
NL_TEST_ASSERT(inSuite, !(v2 == v4));
241+
242+
NL_TEST_ASSERT(inSuite, !(v3 == v0));
243+
NL_TEST_ASSERT(inSuite, !(v3 == v1));
244+
NL_TEST_ASSERT(inSuite, (v3 == v2));
245+
NL_TEST_ASSERT(inSuite, (v3 == v3));
246+
NL_TEST_ASSERT(inSuite, !(v3 == v4));
247+
248+
NL_TEST_ASSERT(inSuite, !(v4 == v0));
249+
NL_TEST_ASSERT(inSuite, !(v4 == v1));
250+
NL_TEST_ASSERT(inSuite, !(v4 == v2));
251+
NL_TEST_ASSERT(inSuite, !(v4 == v3));
252+
NL_TEST_ASSERT(inSuite, (v4 == v4));
253+
}
254+
216255
int Setup(void * inContext)
217256
{
218257
return SUCCESS;
@@ -229,10 +268,11 @@ int Teardown(void * inContext)
229268
/**
230269
* Test Suite. It lists all the test functions.
231270
*/
232-
static const nlTest sTests[] = { NL_TEST_DEF_FN(TestVariantSimple), NL_TEST_DEF_FN(TestVariantMovable),
233-
NL_TEST_DEF_FN(TestVariantCtorDtor), NL_TEST_DEF_FN(TestVariantCopy),
234-
NL_TEST_DEF_FN(TestVariantMove), NL_TEST_DEF_FN(TestVariantCopyAssign),
235-
NL_TEST_DEF_FN(TestVariantMoveAssign), NL_TEST_SENTINEL() };
271+
static const nlTest sTests[] = {
272+
NL_TEST_DEF_FN(TestVariantSimple), NL_TEST_DEF_FN(TestVariantMovable), NL_TEST_DEF_FN(TestVariantCtorDtor),
273+
NL_TEST_DEF_FN(TestVariantCopy), NL_TEST_DEF_FN(TestVariantMove), NL_TEST_DEF_FN(TestVariantCopyAssign),
274+
NL_TEST_DEF_FN(TestVariantMoveAssign), NL_TEST_DEF_FN(TestVariantCompare), NL_TEST_SENTINEL()
275+
};
236276

237277
int TestVariant()
238278
{

0 commit comments

Comments
 (0)