LCOV - code coverage report
Current view: top level - variable/include/scipp/variable - variable_keyword_arg_constructor.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 24 27 88.9 %
Date: 2024-04-28 01:25:40 Functions: 107 159 67.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: BSD-3-Clause
       2             : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
       3             : /// @file
       4             : /// @author Simon Heybrock
       5             : #pragma once
       6             : 
       7             : #include <optional>
       8             : #include <type_traits>
       9             : 
      10             : #include "scipp/core/dimensions.h"
      11             : #include "scipp/core/dtype.h"
      12             : #include "scipp/core/element_array.h"
      13             : #include "scipp/units/dim.h"
      14             : #include "scipp/units/unit.h"
      15             : 
      16             : #include "scipp-variable_export.h"
      17             : 
      18             : namespace scipp::variable {
      19             : 
      20             : namespace detail {
      21             : template <class U> struct vector {
      22             :   std::vector<U> data;
      23             :   template <class... Args>
      24     1365521 :   vector(Args &&...args) : data(std::forward<Args>(args)...) {}
      25             :   template <class A, class B> // avoid use of vector(size, value)
      26             :   vector(A &&a, B &&b) : data(std::initializer_list<U>{a, b}) {}
      27             :   template <class T>
      28        1004 :   vector(std::initializer_list<T> init) : data(init.begin(), init.end()) {}
      29             : };
      30             : 
      31             : template <template <class...> class Derived, class... Args> struct arg_tuple {
      32             :   std::tuple<std::decay_t<Args>...> tuple;
      33      673931 :   arg_tuple(Args &&...args) : tuple(std::forward<Args>(args)...) {}
      34             : };
      35             : } // namespace detail
      36             : 
      37             : using Shape = detail::vector<scipp::index>;
      38             : using Dims = detail::vector<Dim>;
      39             : 
      40             : template <class... Args>
      41             : struct Values : public detail::arg_tuple<Values, Args...> {
      42             :   using detail::arg_tuple<Values, Args...>::arg_tuple;
      43             :   template <class T>
      44             :   Values(std::initializer_list<T> init)
      45             :       : detail::arg_tuple<Values, Args...>(std::move(init)) {}
      46             : };
      47             : template <class... Args>
      48             : struct Variances : public detail::arg_tuple<Variances, Args...> {
      49             :   using detail::arg_tuple<Variances, Args...>::arg_tuple;
      50             :   template <class T>
      51             :   Variances(std::initializer_list<T> init)
      52             :       : detail::arg_tuple<Variances, Args...>(std::move(init)) {}
      53             : };
      54             : 
      55             : template <class... Args> Values(Args &&...args) -> Values<Args...>;
      56             : template <class T>
      57             : Values(std::initializer_list<T>) -> Values<std::initializer_list<T>>;
      58             : 
      59             : template <class... Args> Variances(Args &&...args) -> Variances<Args...>;
      60             : template <class T>
      61             : Variances(std::initializer_list<T>) -> Variances<std::initializer_list<T>>;
      62             : 
      63             : namespace detail {
      64             : 
      65             : SCIPP_VARIABLE_EXPORT void
      66             : throw_keyword_arg_constructor_bad_dtype(const DType dtype);
      67             : 
      68             : /// Convert "keyword" args to tuple that can be used to construct Variable
      69             : ///
      70             : /// This is an implementation detail of `makeVariable`.
      71             : template <class ElemT> struct ArgParser {
      72             :   std::tuple<std::optional<units::Unit>, Dimensions, element_array<ElemT>,
      73             :              std::optional<element_array<ElemT>>>
      74             :       args;
      75             :   Dims dims;
      76             :   Shape shape;
      77             : 
      78      641887 :   void parse(const units::Unit &arg) {
      79      641887 :     std::get<std::optional<units::Unit>>(args) = arg;
      80      641887 :   }
      81             : 
      82       68516 :   void parse(const Dimensions &arg) { std::get<Dimensions>(args) = arg; }
      83             : 
      84         502 :   void parse(const Dims &arg) {
      85         502 :     if (shape.data.empty())
      86         502 :       dims = arg;
      87             :     else
      88           0 :       std::get<Dimensions>(args) = Dimensions(arg.data, shape.data);
      89         502 :   }
      90             : 
      91         529 :   void parse(const Shape &arg) {
      92         529 :     if (dims.data.empty())
      93          27 :       shape = arg;
      94             :     else
      95         502 :       std::get<Dimensions>(args) = Dimensions(dims.data, arg.data);
      96         529 :   }
      97             : 
      98      673165 :   template <class... Args> void parse(Values<Args...> &&arg) {
      99             :     if constexpr (std::is_constructible_v<element_array<ElemT>, Args...>)
     100      673165 :       std::get<2>(args) =
     101      673165 :           std::make_from_tuple<element_array<ElemT>>(std::move(arg.tuple));
     102             :     else
     103           0 :       throw_keyword_arg_constructor_bad_dtype(core::dtype<ElemT>);
     104      673165 :   }
     105             : 
     106         766 :   template <class... Args> void parse(Variances<Args...> &&arg) {
     107             :     if constexpr (std::is_constructible_v<element_array<ElemT>, Args...>)
     108         766 :       std::get<3>(args) =
     109         766 :           std::make_from_tuple<element_array<ElemT>>(std::move(arg.tuple));
     110             :     else
     111           0 :       throw_keyword_arg_constructor_bad_dtype(core::dtype<ElemT>);
     112         766 :   }
     113             : };
     114             : 
     115             : } // namespace detail
     116             : } // namespace scipp::variable

Generated by: LCOV version 1.14