Ad
Code
Diff
  • #include <utility>
    
    template<typename T, typename U>
    constexpr auto multiply(T a, U b) -> decltype(std::declval<T>() * std::declval<U>()){
      return a * b;
    }
    • #define multiply(a,b) a*b
    • #include <utility>
    • template<typename T, typename U>
    • constexpr auto multiply(T a, U b) -> decltype(std::declval<T>() * std::declval<U>()){
    • return a * b;
    • }

I know this doesn't work in the current c+ version. Needs c++20.
But with concepts, some of this can be simplified

Concept to check if T + T is valid.
Concept to check if U(T + T) + T is valid, and is U.

T + T could give a different type U, but T + U must be U again.

Code
Diff
  • /*
    #include <concepts>
    #include <vector>
    #include <numeric>
    #include <type_traits>
    
    namespace{
        // Concept to check if T + T yields a valid type
        template <typename T>
        concept SelfAddable = requires(T a) {
            { a + a }; // Ensure T + T is valid
        };
    
    // Concept to check if U + T is valid and results in U
        template <typename T, typename U>
        concept CompatibleAddable = requires(U u, T t) {
            { u + t } -> std::same_as<U>;
        };
    
    // Function template with inferred U
        template <SelfAddable T>
        requires CompatibleAddable<T, decltype(std::declval<T>() + std::declval<T>())>
        auto sum(const std::vector<T>& v) {
            using U = decltype(std::declval<T>() + std::declval<T>()); // Infer U
            return std::accumulate(v.cbegin(), v.cend(), U{}, [](U acc, const T& elem) {
                return acc + elem;
            });
        }
    }
    */
    
    
    
    //OLD
    #include <vector>
    #include <numeric>
    #include <type_traits>
    #include <utility>
    
    namespace
    {
      template<typename, typename, typename = void>
      struct has_plus : std::false_type {};
    
      template<typename T1, typename T2>
      struct has_plus<T1, T2, std::void_t<decltype(std::declval<T1>() + std::declval<T2>())>> : std::true_type {};
    
      template<typename T1, typename T2>
      inline constexpr bool has_plus_v = has_plus<T1, T2>::value;
    
      template<typename T1, typename T2, bool = has_plus_v<T1, T2>>
      struct plus_result
      {
        using type = decltype(std::declval<T1>() + std::declval<T2>());
      };
      
      template<typename T1, typename T2>
      struct plus_result<T1, T2, false> {};
      
      template<typename T1, typename T2>
      using plus_result_t = typename plus_result<T1, T2>::type;
      
      template<typename T = double, typename = std::enable_if_t<has_plus_v<T, T>>>
      plus_result_t<T, T> sum(const std::vector<T>& v)
      {
        return std::accumulate(v.cbegin(), v.cend(), T{});
      }
    }
    • /*
    • #include <concepts>
    • #include <vector>
    • #include <numeric>
    • #include <type_traits>
    • namespace{
    • // Concept to check if T + T yields a valid type
    • template <typename T>
    • concept SelfAddable = requires(T a) {
    • { a + a }; // Ensure T + T is valid
    • };
    • // Concept to check if U + T is valid and results in U
    • template <typename T, typename U>
    • concept CompatibleAddable = requires(U u, T t) {
    • { u + t } -> std::same_as<U>;
    • };
    • // Function template with inferred U
    • template <SelfAddable T>
    • requires CompatibleAddable<T, decltype(std::declval<T>() + std::declval<T>())>
    • auto sum(const std::vector<T>& v) {
    • using U = decltype(std::declval<T>() + std::declval<T>()); // Infer U
    • return std::accumulate(v.cbegin(), v.cend(), U{}, [](U acc, const T& elem) {
    • return acc + elem;
    • });
    • }
    • }
    • */
    • //OLD
    • #include <vector>
    • #include <numeric>
    • #include <type_traits>
    • #include <utility>
    • namespace
    • {
    • template<typename, typename, typename = void>
    • struct has_plus : std::false_type {};
    • template<typename T1, typename T2>
    • struct has_plus<T1, T2, std::void_t<decltype(std::declval<T1>() + std::declval<T2>())>> : std::true_type {};
    • template<typename T1, typename T2>
    • inline constexpr bool has_plus_v = has_plus<T1, T2>::value;
    • template<typename T1, typename T2, bool = has_plus_v<T1, T2>>
    • struct plus_result
    • {
    • using type = decltype(std::declval<T1>() + std::declval<T2>());
    • };
    • template<typename T1, typename T2>
    • struct plus_result<T1, T2, false> {};
    • template<typename T1, typename T2>
    • using plus_result_t = typename plus_result<T1, T2>::type;
    • template<typename T = double, typename = std::enable_if_t<has_plus_v<T, T>>>
    • plus_result_t<T, T> sum(const std::vector<T>& v)
    • {
    • return std::accumulate(v.cbegin(), v.cend(), T{});
    • }
    • }