@@ -245,6 +245,37 @@ constexpr auto exact_rep_cast(SrcRep value)
245245 }
246246}
247247
248+ template <underlying_type Dest, underlying_type Src, typename RepCaster>
249+ constexpr auto cast_underlying_value (Src value, RepCaster rep_caster) -> Dest {
250+ using src_type = std::remove_cv_t <Src>;
251+ using dest_type = std::remove_cv_t <Dest>;
252+ using src_rep_type = underlying::traits<src_type>::rep_type;
253+ using dest_rep_type = underlying::traits<dest_type>::rep_type;
254+
255+ auto const source_rep = underlying::traits<src_type>::to_rep (value);
256+ auto const target_rep = rep_caster.template operator ()<dest_rep_type>(
257+ static_cast <src_rep_type>(source_rep));
258+ return underlying::traits<dest_type>::from_rep (target_rep);
259+ }
260+
261+ template <underlying_type Dest, underlying_type Src, typename RepCaster>
262+ constexpr auto cast_underlying_result (Src value, RepCaster rep_caster)
263+ -> cast_result<Dest> {
264+ using src_type = std::remove_cv_t <Src>;
265+ using dest_type = std::remove_cv_t <Dest>;
266+ using src_rep_type = underlying::traits<src_type>::rep_type;
267+ using dest_rep_type = underlying::traits<dest_type>::rep_type;
268+
269+ auto const source_rep = underlying::traits<src_type>::to_rep (value);
270+ auto const target_rep = rep_caster.template operator ()<dest_rep_type>(
271+ static_cast <src_rep_type>(source_rep));
272+ if (!target_rep.has_value ()) {
273+ return std::unexpected (target_rep.error ());
274+ }
275+
276+ return underlying::traits<dest_type>::from_rep (*target_rep);
277+ }
278+
248279} // namespace mcpplibs::primitives::conversion::details
249280
250281export namespace mcpplibs ::primitives::conversion {
@@ -310,75 +341,42 @@ constexpr auto exact_cast(SrcRep value)
310341
311342template <underlying_type Dest, underlying_type Src>
312343constexpr auto unchecked_cast (Src value) noexcept -> Dest {
313- using src_type = std::remove_cv_t <Src>;
314- using dest_type = std::remove_cv_t <Dest>;
315- using src_rep_type = underlying::traits<src_type>::rep_type;
316- using dest_rep_type = underlying::traits<dest_type>::rep_type;
317-
318- auto const source_rep = underlying::traits<src_type>::to_rep (value);
319- auto const target_rep =
320- details::unchecked_rep_cast<dest_rep_type>(static_cast <src_rep_type>(source_rep));
321- return underlying::traits<dest_type>::from_rep (target_rep);
344+ return details::cast_underlying_value<Dest>(
345+ value, []<typename DestRep, typename SrcRep>(SrcRep rep) {
346+ return details::unchecked_rep_cast<DestRep>(rep);
347+ });
322348}
323349
324350template <underlying_type Dest, underlying_type Src>
325351constexpr auto checked_cast (Src value) -> cast_result<Dest> {
326- using src_type = std::remove_cv_t <Src>;
327- using dest_type = std::remove_cv_t <Dest>;
328- using src_rep_type = underlying::traits<src_type>::rep_type;
329- using dest_rep_type = underlying::traits<dest_type>::rep_type;
330-
331- auto const source_rep = underlying::traits<src_type>::to_rep (value);
332- auto const target_rep =
333- details::checked_rep_cast<dest_rep_type>(static_cast <src_rep_type>(source_rep));
334- if (!target_rep.has_value ()) {
335- return std::unexpected (target_rep.error ());
336- }
337-
338- return underlying::traits<dest_type>::from_rep (*target_rep);
352+ return details::cast_underlying_result<Dest>(
353+ value, []<typename DestRep, typename SrcRep>(SrcRep rep) {
354+ return details::checked_rep_cast<DestRep>(rep);
355+ });
339356}
340357
341358template <underlying_type Dest, underlying_type Src>
342359constexpr auto saturating_cast (Src value) noexcept -> Dest {
343- using src_type = std::remove_cv_t <Src>;
344- using dest_type = std::remove_cv_t <Dest>;
345- using src_rep_type = underlying::traits<src_type>::rep_type;
346- using dest_rep_type = underlying::traits<dest_type>::rep_type;
347-
348- auto const source_rep = underlying::traits<src_type>::to_rep (value);
349- auto const target_rep =
350- details::saturating_rep_cast<dest_rep_type>(static_cast <src_rep_type>(source_rep));
351- return underlying::traits<dest_type>::from_rep (target_rep);
360+ return details::cast_underlying_value<Dest>(
361+ value, []<typename DestRep, typename SrcRep>(SrcRep rep) {
362+ return details::saturating_rep_cast<DestRep>(rep);
363+ });
352364}
353365
354366template <underlying_type Dest, underlying_type Src>
355367constexpr auto truncating_cast (Src value) noexcept -> Dest {
356- using src_type = std::remove_cv_t <Src>;
357- using dest_type = std::remove_cv_t <Dest>;
358- using src_rep_type = underlying::traits<src_type>::rep_type;
359- using dest_rep_type = underlying::traits<dest_type>::rep_type;
360-
361- auto const source_rep = underlying::traits<src_type>::to_rep (value);
362- auto const target_rep =
363- details::truncating_rep_cast<dest_rep_type>(static_cast <src_rep_type>(source_rep));
364- return underlying::traits<dest_type>::from_rep (target_rep);
368+ return details::cast_underlying_value<Dest>(
369+ value, []<typename DestRep, typename SrcRep>(SrcRep rep) {
370+ return details::truncating_rep_cast<DestRep>(rep);
371+ });
365372}
366373
367374template <underlying_type Dest, underlying_type Src>
368375constexpr auto exact_cast (Src value) -> cast_result<Dest> {
369- using src_type = std::remove_cv_t <Src>;
370- using dest_type = std::remove_cv_t <Dest>;
371- using src_rep_type = underlying::traits<src_type>::rep_type;
372- using dest_rep_type = underlying::traits<dest_type>::rep_type;
373-
374- auto const source_rep = underlying::traits<src_type>::to_rep (value);
375- auto const target_rep =
376- details::exact_rep_cast<dest_rep_type>(static_cast <src_rep_type>(source_rep));
377- if (!target_rep.has_value ()) {
378- return std::unexpected (target_rep.error ());
379- }
380-
381- return underlying::traits<dest_type>::from_rep (*target_rep);
376+ return details::cast_underlying_result<Dest>(
377+ value, []<typename DestRep, typename SrcRep>(SrcRep rep) {
378+ return details::exact_rep_cast<DestRep>(rep);
379+ });
382380}
383381
384382} // namespace mcpplibs::primitives::conversion
0 commit comments