# Changeset View

Changeset View

# Standalone View

Standalone View

# test/support/uses_alloc_types.hpp

- This file was added.

1 | //===----------------------------------------------------------------------===// | ||||
---|---|---|---|---|---|

2 | // | ||||

3 | // The LLVM Compiler Infrastructure | ||||

4 | // | ||||

5 | // This file is dual licensed under the MIT and the University of Illinois Open | ||||

6 | // Source Licenses. See LICENSE.TXT for details. | ||||

7 | // | ||||

8 | //===----------------------------------------------------------------------===// | ||||

9 | | ||||

10 | #ifndef USES_ALLOC_TYPES_HPP | ||||

11 | #define USES_ALLOC_TYPES_HPP | ||||

12 | | ||||

13 | # include <experimental/memory_resource> | ||||

14 | # include <experimental/utility> | ||||

15 | # include <memory> | ||||

16 | # include <cassert> | ||||

17 | | ||||

18 | #include "test_memory_resource.hpp" | ||||

19 | #include "type_id.h" | ||||

20 | | ||||

21 | // There are two forms of uses-allocator construction: | ||||

22 | // (1) UA_AllocArg: 'T(allocator_arg_t, Alloc const&, Args&&...)' | ||||

23 | // (2) UA_AllocLast: 'T(Args&&..., Alloc const&)' | ||||

24 | // 'UA_None' represents non-uses allocator construction. | ||||

25 | enum class UsesAllocatorType { | ||||

26 | UA_None = 0, | ||||

27 | UA_AllocArg = 2, | ||||

28 | UA_AllocLast = 4 | ||||

29 | }; | ||||

30 | constexpr UsesAllocatorType UA_None = UsesAllocatorType::UA_None; | ||||

31 | constexpr UsesAllocatorType UA_AllocArg = UsesAllocatorType::UA_AllocArg; | ||||

32 | constexpr UsesAllocatorType UA_AllocLast = UsesAllocatorType::UA_AllocLast; | ||||

33 | | ||||

34 | template <class Alloc, std::size_t N> | ||||

35 | class UsesAllocatorV1; | ||||

36 | // Implements form (1) of uses-allocator construction from the specified | ||||

37 | // 'Alloc' type and exactly 'N' additional arguments. It also provides | ||||

38 | // non-uses allocator construction from 'N' arguments. This test type | ||||

39 | // blows up when form (2) of uses-allocator is even considered. | ||||

40 | | ||||

41 | template <class Alloc, std::size_t N> | ||||

42 | class UsesAllocatorV2; | ||||

43 | // Implements form (2) of uses-allocator construction from the specified | ||||

44 | // 'Alloc' type and exactly 'N' additional arguments. It also provides | ||||

45 | // non-uses allocator construction from 'N' arguments. | ||||

46 | | ||||

47 | template <class Alloc, std::size_t N> | ||||

48 | class UsesAllocatorV3; | ||||

49 | // Implements both form (1) and (2) of uses-allocator construction from | ||||

50 | // the specified 'Alloc' type and exactly 'N' additional arguments. It also | ||||

51 | // provides non-uses allocator construction from 'N' arguments. | ||||

52 | | ||||

53 | template <class Alloc, std::size_t> | ||||

54 | class NotUsesAllocator; | ||||

55 | // Implements both form (1) and (2) of uses-allocator construction from | ||||

56 | // the specified 'Alloc' type and exactly 'N' additional arguments. It also | ||||

57 | // provides non-uses allocator construction from 'N' arguments. However | ||||

58 | // 'NotUsesAllocator' never provides a 'allocator_type' typedef so it is | ||||

59 | // never automatically uses-allocator constructed. | ||||

60 | | ||||

61 | | ||||

62 | template <class ...ArgTypes, class TestType> | ||||

63 | bool checkConstruct(TestType& value, UsesAllocatorType form, | ||||

64 | typename TestType::CtorAlloc const& alloc) | ||||

65 | // Check that 'value' was constructed using the specified 'form' of | ||||

66 | // construction and with the specified 'ArgTypes...'. Additionally | ||||

67 | // check that 'value' was constructed using the specified 'alloc'. | ||||

68 | { | ||||

69 | if (form == UA_None) { | ||||

70 | return value.template checkConstruct<ArgTypes&&...>(form); | ||||

71 | } else { | ||||

72 | return value.template checkConstruct<ArgTypes&&...>(form, alloc); | ||||

73 | } | ||||

74 | } | ||||

75 | | ||||

76 | | ||||

77 | template <class ...ArgTypes, class TestType> | ||||

78 | bool checkConstruct(TestType& value, UsesAllocatorType form) { | ||||

79 | return value.template checkConstruct<ArgTypes&&...>(form); | ||||

80 | } | ||||

81 | | ||||

82 | template <class TestType> | ||||

83 | bool checkConstructionEquiv(TestType& T, TestType& U) | ||||

84 | // check that 'T' and 'U' where initialized in the exact same manner. | ||||

85 | { | ||||

86 | return T.checkConstructEquiv(U); | ||||

87 | } | ||||

88 | | ||||

89 | //////////////////////////////////////////////////////////////////////////////// | ||||

90 | namespace detail { | ||||

91 | | ||||

92 | template <bool IsZero, size_t N, class ArgList, class ...Args> | ||||

93 | struct TakeNImp; | ||||

94 | | ||||

95 | template <class ArgList, class ...Args> | ||||

96 | struct TakeNImp<true, 0, ArgList, Args...> { | ||||

97 | typedef ArgList type; | ||||

98 | }; | ||||

99 | | ||||

100 | template <size_t N, class ...A1, class F, class ...R> | ||||

101 | struct TakeNImp<false, N, ArgumentListID<A1...>, F, R...> | ||||

102 | : TakeNImp<N-1 == 0, N - 1, ArgumentListID<A1..., F>, R...> {}; | ||||

103 | | ||||

104 | template <size_t N, class ...Args> | ||||

105 | struct TakeNArgs : TakeNImp<N == 0, N, ArgumentListID<>, Args...> {}; | ||||

106 | | ||||

107 | template <class T> | ||||

108 | struct Identity { typedef T type; }; | ||||

109 | | ||||

110 | template <class T> | ||||

111 | using IdentityT = typename Identity<T>::type; | ||||

112 | | ||||

113 | template <bool Value> | ||||

114 | using EnableIfB = typename std::enable_if<Value, bool>::type; | ||||

115 | | ||||

116 | } // end namespace detail | ||||

117 | | ||||

118 | using detail::EnableIfB; | ||||

119 | | ||||

120 | struct AllocLastTag {}; | ||||

121 | | ||||

122 | template <class Alloc> | ||||

123 | struct UsesAllocatorTestBase { | ||||

124 | public: | ||||

125 | using CtorAlloc = typename std::conditional< | ||||

126 | std::is_same<Alloc, std::experimental::erased_type>::value, | ||||

127 | std::experimental::pmr::memory_resource*, | ||||

128 | Alloc | ||||

129 | >::type; | ||||

130 | | ||||

131 | template <class ...ArgTypes> | ||||

132 | bool checkConstruct(UsesAllocatorType expectType) const { | ||||

133 | return expectType == constructor_called && | ||||

134 | makeArgumentID<ArgTypes...>() == *args_id; | ||||

135 | } | ||||

136 | | ||||

137 | template <class ...ArgTypes> | ||||

138 | bool checkConstruct(UsesAllocatorType expectType, | ||||

139 | CtorAlloc const& expectAlloc) const { | ||||

140 | return expectType == constructor_called && | ||||

141 | makeArgumentID<ArgTypes...>() == *args_id && | ||||

142 | expectAlloc == allocator; | ||||

143 | } | ||||

144 | | ||||

145 | bool checkConstructEquiv(UsesAllocatorTestBase& O) const { | ||||

146 | return constructor_called == O.constructor_called | ||||

147 | && *args_id == *O.args_id | ||||

148 | && allocator == O.allocator; | ||||

149 | } | ||||

150 | | ||||

151 | protected: | ||||

152 | explicit UsesAllocatorTestBase(const TypeID* aid) | ||||

153 | : args_id(aid), constructor_called(UA_None), allocator() | ||||

154 | {} | ||||

155 | | ||||

156 | template <class ...Args> | ||||

157 | UsesAllocatorTestBase(std::allocator_arg_t, CtorAlloc const& a, Args&&...) | ||||

158 | : args_id(&makeArgumentID<Args&&...>()), | ||||

159 | constructor_called(UA_AllocArg), | ||||

160 | allocator(a) | ||||

161 | {} | ||||

162 | | ||||

163 | template <class ...Args> | ||||

164 | UsesAllocatorTestBase(AllocLastTag, Args&&... args) | ||||

165 | : args_id(nullptr), | ||||

166 | constructor_called(UA_AllocLast) | ||||

167 | { | ||||

168 | typedef typename detail::TakeNArgs<sizeof...(Args) - 1, Args&&...>::type | ||||

169 | ArgIDL; | ||||

170 | args_id = &makeTypeID<ArgIDL>(); | ||||

171 | getAllocatorFromPack(ArgIDL{}, std::forward<Args>(args)...); | ||||

172 | } | ||||

173 | | ||||

174 | private: | ||||

175 | template <class ...LArgs, class ...Args> | ||||

176 | void getAllocatorFromPack(ArgumentListID<LArgs...>, Args&&... args) { | ||||

177 | getAllocatorFromPackImp<LArgs const&...>(args...); | ||||

178 | } | ||||

179 | | ||||

180 | template <class ...LArgs> | ||||

181 | void getAllocatorFromPackImp(typename detail::Identity<LArgs>::type..., CtorAlloc const& alloc) { | ||||

182 | allocator = alloc; | ||||

183 | } | ||||

184 | | ||||

185 | const TypeID* args_id; | ||||

186 | UsesAllocatorType constructor_called = UA_None; | ||||

187 | CtorAlloc allocator; | ||||

188 | }; | ||||

189 | | ||||

190 | template <class Alloc, size_t Arity> | ||||

191 | class UsesAllocatorV1 : public UsesAllocatorTestBase<Alloc> | ||||

192 | { | ||||

193 | public: | ||||

194 | typedef Alloc allocator_type; | ||||

195 | | ||||

196 | using Base = UsesAllocatorTestBase<Alloc>; | ||||

197 | using CtorAlloc = typename Base::CtorAlloc; | ||||

198 | | ||||

199 | UsesAllocatorV1() : Base(&makeArgumentID<>()) {} | ||||

200 | | ||||

201 | // Non-Uses Allocator Ctor | ||||

202 | template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false> | ||||

203 | UsesAllocatorV1(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {}; | ||||

204 | | ||||

205 | // Uses Allocator Arg Ctor | ||||

206 | template <class ...Args> | ||||

207 | UsesAllocatorV1(std::allocator_arg_t tag, CtorAlloc const & a, Args&&... args) | ||||

208 | : Base(tag, a, std::forward<Args>(args)...) | ||||

209 | { } | ||||

210 | | ||||

211 | // BLOWS UP: Uses Allocator Last Ctor | ||||

212 | template <class _First, class ...Args, EnableIfB<sizeof...(Args) == Arity> _Dummy = false> | ||||

213 | constexpr UsesAllocatorV1(_First&& __first, Args&&... args) | ||||

214 | { | ||||

215 | static_assert(!std::is_same<_First, _First>::value, ""); | ||||

216 | } | ||||

217 | }; | ||||

218 | | ||||

219 | | ||||

220 | template <class Alloc, size_t Arity> | ||||

221 | class UsesAllocatorV2 : public UsesAllocatorTestBase<Alloc> | ||||

222 | { | ||||

223 | public: | ||||

224 | typedef Alloc allocator_type; | ||||

225 | | ||||

226 | using Base = UsesAllocatorTestBase<Alloc>; | ||||

227 | using CtorAlloc = typename Base::CtorAlloc; | ||||

228 | | ||||

229 | UsesAllocatorV2() : Base(&makeArgumentID<>()) {} | ||||

230 | | ||||

231 | // Non-Uses Allocator Ctor | ||||

232 | template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false> | ||||

233 | UsesAllocatorV2(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {}; | ||||

234 | | ||||

235 | // Uses Allocator Last Ctor | ||||

236 | template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false> | ||||

237 | UsesAllocatorV2(Args&&... args) | ||||

238 | : Base(AllocLastTag{}, std::forward<Args>(args)...) | ||||

239 | {} | ||||

240 | }; | ||||

241 | | ||||

242 | template <class Alloc, size_t Arity> | ||||

243 | class UsesAllocatorV3 : public UsesAllocatorTestBase<Alloc> | ||||

244 | { | ||||

245 | public: | ||||

246 | typedef Alloc allocator_type; | ||||

247 | | ||||

248 | using Base = UsesAllocatorTestBase<Alloc>; | ||||

249 | using CtorAlloc = typename Base::CtorAlloc; | ||||

250 | | ||||

251 | UsesAllocatorV3() : Base(&makeArgumentID<>()) {} | ||||

252 | | ||||

253 | // Non-Uses Allocator Ctor | ||||

254 | template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false> | ||||

255 | UsesAllocatorV3(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {}; | ||||

256 | | ||||

257 | // Uses Allocator Arg Ctor | ||||

258 | template <class ...Args> | ||||

259 | UsesAllocatorV3(std::allocator_arg_t tag, CtorAlloc const& alloc, Args&&... args) | ||||

260 | : Base(tag, alloc, std::forward<Args>(args)...) | ||||

261 | {} | ||||

262 | | ||||

263 | // Uses Allocator Last Ctor | ||||

264 | template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false> | ||||

265 | UsesAllocatorV3(Args&&... args) | ||||

266 | : Base(AllocLastTag{}, std::forward<Args>(args)...) | ||||

267 | {} | ||||

268 | }; | ||||

269 | | ||||

270 | template <class Alloc, size_t Arity> | ||||

271 | class NotUsesAllocator : public UsesAllocatorTestBase<Alloc> | ||||

272 | { | ||||

273 | public: | ||||

274 | // no allocator_type typedef provided | ||||

275 | | ||||

276 | using Base = UsesAllocatorTestBase<Alloc>; | ||||

277 | using CtorAlloc = typename Base::CtorAlloc; | ||||

278 | | ||||

279 | NotUsesAllocator() : Base(&makeArgumentID<>()) {} | ||||

280 | | ||||

281 | // Non-Uses Allocator Ctor | ||||

282 | template <class ...Args, EnableIfB<sizeof...(Args) == Arity> = false> | ||||

283 | NotUsesAllocator(Args&&... args) : Base(&makeArgumentID<Args&&...>()) {}; | ||||

284 | | ||||

285 | // Uses Allocator Arg Ctor | ||||

286 | template <class ...Args> | ||||

287 | NotUsesAllocator(std::allocator_arg_t tag, CtorAlloc const& alloc, Args&&... args) | ||||

288 | : Base(tag, alloc, std::forward<Args>(args)...) | ||||

289 | {} | ||||

290 | | ||||

291 | // Uses Allocator Last Ctor | ||||

292 | template <class ...Args, EnableIfB<sizeof...(Args) == Arity + 1> = false> | ||||

293 | NotUsesAllocator(Args&&... args) | ||||

294 | : Base(AllocLastTag{}, std::forward<Args>(args)...) | ||||

295 | {} | ||||

296 | }; | ||||

297 | | ||||

298 | #endif /* USES_ALLOC_TYPES_HPP */ |