Ad
Code
Diff
  • #include <string>
    #include <string_view>
    #include <fmt/format.h>
    #include <cmath>
    #include <array>
    
    namespace{
      using namespace std::literals::string_view_literals;
      constexpr std::array ones_map{"ZERO "sv, "ONE "sv, "TWO "sv, "THREE "sv, "FOUR "sv, "FIVE "sv, "SIX "sv, "SEVEN "sv, "EIGHT "sv, "NINE "sv};
      constexpr std::array teens_map{"TEN "sv, "ELEVEN "sv, "TWELVE "sv, "THIRTEEN "sv, "FOURTEEN "sv, "FIFTEEN "sv, "SIXTEEN "sv, "SEVENTEEN "sv, "EIGHTEEN "sv, "NINETEEN "sv};
      constexpr std::array tens_map{"TWENTY "sv, "THIRTY "sv, "FORTY "sv, "FIFTY "sv, "SIXTY "sv, "SEVENTY "sv, "EIGHTY "sv, "NINETY "sv};
      constexpr std::string_view empty{};
    }
    
    std::string checkAmount(double amount) {
      int totalCents = static_cast<int>( std::round(amount * 100) );
      if (totalCents < 1 || totalCents > 9999) return {};
      
      int dollars   = totalCents / 100;
      int cents = totalCents % 100;
      
      auto tens_word = empty;
      auto ones_word = empty;
      
      if(dollars < 10){
        ones_word = ones_map[dollars];
      } else if(dollars < 20){
        ones_word = teens_map[dollars - 10];
      } else{
        auto ones_val = dollars % 10;
        if(ones_val > 0){
          ones_word = ones_map[ones_val];
        }
        tens_word = tens_map[dollars / 10 - 2];
      }
      
      return fmt::format("{}{}and {}/100", tens_word, ones_word, cents);
    }
    • #include <string.h>
    • #include <stdio.h>
    • #include <stdlib.h>
    • #include <string>
    • #include <string_view>
    • #include <fmt/format.h>
    • #include <cmath>
    • #include <array>
    • char *checkAmount(double amount) {
    • char * return_val = NULL;
    • // Your code here!
    • namespace{
    • using namespace std::literals::string_view_literals;
    • constexpr std::array ones_map{"ZERO "sv, "ONE "sv, "TWO "sv, "THREE "sv, "FOUR "sv, "FIVE "sv, "SIX "sv, "SEVEN "sv, "EIGHT "sv, "NINE "sv};
    • constexpr std::array teens_map{"TEN "sv, "ELEVEN "sv, "TWELVE "sv, "THIRTEEN "sv, "FOURTEEN "sv, "FIFTEEN "sv, "SIXTEEN "sv, "SEVENTEEN "sv, "EIGHTEEN "sv, "NINETEEN "sv};
    • constexpr std::array tens_map{"TWENTY "sv, "THIRTY "sv, "FORTY "sv, "FIFTY "sv, "SIXTY "sv, "SEVENTY "sv, "EIGHTY "sv, "NINETY "sv};
    • constexpr std::string_view empty{};
    • }
    • std::string checkAmount(double amount) {
    • int totalCents = static_cast<int>( std::round(amount * 100) );
    • if (totalCents < 1 || totalCents > 9999) return {};
    • int dollars = totalCents / 100;
    • int cents = totalCents % 100;
    • auto tens_word = empty;
    • auto ones_word = empty;
    • if(dollars < 10){
    • ones_word = ones_map[dollars];
    • } else if(dollars < 20){
    • ones_word = teens_map[dollars - 10];
    • } else{
    • auto ones_val = dollars % 10;
    • if(ones_val > 0){
    • ones_word = ones_map[ones_val];
    • }
    • tens_word = tens_map[dollars / 10 - 2];
    • }
    • return return_val;
    • return fmt::format("{}{}and {}/100", tens_word, ones_word, cents);
    • }
Lists

as the relative order between two equal ints does not matter (and sort would ruin it anyways), we can just use partition, instead of stable_partition.

Added a lot of tests

Code
Diff
  • #include <vector>
    
    void re_arrange(std::vector<int>& data) {
        auto it = std::partition(data.begin(), data.end(), [](int x) { return x % 2 == 0; });
        std::sort(data.begin(), it);
        std::sort(it, data.end());
    }
    • #include <vector>
    • void re_arrange(std::vector<int>& data) {
    • auto it = std::stable_partition(data.begin(), data.end(), [](int x) { return x % 2 == 0; });
    • auto it = std::partition(data.begin(), data.end(), [](int x) { return x % 2 == 0; });
    • std::sort(data.begin(), it);
    • std::sort(it, data.end());
    • }

Actually makes the input greater than 2
But only if it wasn't already

Code
Diff
  • template<typename T>
    bool above_two(T& arg){
      static_assert(std::is_arithmetic<T>::value, "arg must be a arithmetic type");
      if(arg <= T(2)){
        arg = T(3);
      }
      return true;
    }
    • #Onelined again...
    • def above_two(arg): return True
    • template<typename T>
    • bool above_two(T& arg){
    • static_assert(std::is_arithmetic<T>::value, "arg must be a arithmetic type");
    • if(arg <= T(2)){
    • arg = T(3);
    • }
    • return true;
    • }
Algorithms

Added memory ordering

Increment should just need relaxed, as it does not controll other states. It either keeps the potential object from being reclaimed, in which case there is no change, or the object is already reclaimed and you don't touch it anyway.

all else is more or less acq_rel to sync possible last access to an object, and it's destructor

Code
Diff
  • #include <atomic>
    
    struct Counter {
      static constexpr uint64_t is_zero = 1ull << 63;
      static constexpr uint64_t helped = 1ull << 62;
      std::atomic<uint64_t> counter{1};
      
      bool increment_if_not_zero(){
        return (counter.fetch_add(1, std::memory_order_relaxed) & is_zero) == 0;
      }
      
      bool decrement(){
        if(counter.fetch_sub(1, std::memory_order_acq_rel) == 1){
          uint64_t e = 0;
          if(counter.compare_exchange_strong(e, is_zero, std::memory_order_acq_rel, std::memory_order_acquire)) return true;
          else if((e & helped) && (counter.exchange(is_zero, std::memory_order_acq_rel) & helped)) return true;
        }
        return false;
      }
      
      uint64_t read(){
        auto val = counter.load(std::memory_order_acquire);
        if(val == 0 && counter.compare_exchange_strong(val, is_zero | helped, std::memory_order_acq_rel, std::memory_order_acquire)) return 0;
        return (val & is_zero) ? 0 : val;
      }
    };
    • #include <atomic>
    • struct Counter {
    • static constexpr uint64_t is_zero = 1ull << 63;
    • static constexpr uint64_t helped = 1ull << 62;
    • std::atomic<uint64_t> counter{1};
    • bool increment_if_not_zero(){
    • return (counter.fetch_add(1) & is_zero) == 0;
    • return (counter.fetch_add(1, std::memory_order_relaxed) & is_zero) == 0;
    • }
    • bool decrement(){
    • if(counter.fetch_sub(1) == 1){
    • if(counter.fetch_sub(1, std::memory_order_acq_rel) == 1){
    • uint64_t e = 0;
    • if(counter.compare_exchange_strong(e, is_zero)) return true;
    • else if((e & helped) && (counter.exchange(is_zero) & helped)) return true;
    • if(counter.compare_exchange_strong(e, is_zero, std::memory_order_acq_rel, std::memory_order_acquire)) return true;
    • else if((e & helped) && (counter.exchange(is_zero, std::memory_order_acq_rel) & helped)) return true;
    • }
    • return false;
    • }
    • uint64_t read(){
    • auto val = counter.load();
    • if(val == 0 && counter.compare_exchange_strong(val, is_zero | helped)) return 0;
    • auto val = counter.load(std::memory_order_acquire);
    • if(val == 0 && counter.compare_exchange_strong(val, is_zero | helped, std::memory_order_acq_rel, std::memory_order_acquire)) return 0;
    • return (val & is_zero) ? 0 : val;
    • }
    • };
Code
Diff
  • #include <string>
    #include <string_view>
    #include <algorithm>
    
    std::string fun(std::string_view input)
    {
      std::string result;
      result.reserve(input.size());
      std::transform(input.cbegin(), input.cend(), std::back_inserter(result), [](unsigned char c) -> char {
        return std::toupper(c);
      });
      
      return result;
    }
    • #include <stdlib.h>
    • #include <string.h>
    • #include <ctype.h>
    • #include <string>
    • #include <string_view>
    • #include <algorithm>
    • char *fun(const char *input)
    • std::string fun(std::string_view input)
    • {
    • size_t len = strlen(input);
    • char *result = malloc(len + 1);
    • for (size_t i = 0; input[i]; i++)
    • result[i] = toupper(input[i]);
    • return result[len] = '\0', result;
    • std::string result;
    • result.reserve(input.size());
    • std::transform(input.cbegin(), input.cend(), std::back_inserter(result), [](unsigned char c) -> char {
    • return std::toupper(c);
    • });
    • return result;
    • }

const correctness

Code
Diff
  • #include <stdlib.h>
    #include <string.h>
    
    char *reverse_string(const char *word)
    {
      size_t  len = strlen(word);
      char   *res = malloc(len + 1);
      for (size_t i = 0; i < len; i++)
        res[i] = word[len - i - 1];
      return res[len] = '\0', res;
    }
    • #include <stdlib.h>
    • #include <string.h>
    • char *reverse_string(char *word)
    • char *reverse_string(const char *word)
    • {
    • size_t len = strlen(word);
    • char *res = malloc(len + 1);
    • for (size_t i = 0; i < len; i++)
    • res[i] = word[len - i - 1];
    • return res[len] = '\0', res;
    • }
Algorithms

Wait free counter for use in reference counting, so you know if you are the one who needs to free the memory. Taken from Daniel Anderson - CppCon 2024

I assume you might be able to be optimised more, if you inlude more fine grained memory ordering in each atomic operation.

And it would be prudent to include concurency test, to ensure that only one thread would get a true on decrement.

#include <atomic>

struct Counter {
  static constexpr uint64_t is_zero = 1ull << 63;
  static constexpr uint64_t helped = 1ull << 62;
  std::atomic<uint64_t> counter{1};
  
  bool increment_if_not_zero(){
    return (counter.fetch_add(1) & is_zero) == 0;
  }
  
  bool decrement(){
    if(counter.fetch_sub(1) == 1){
      uint64_t e = 0;
      if(counter.compare_exchange_strong(e, is_zero)) return true;
      else if((e & helped) && (counter.exchange(is_zero) & helped)) return true;
    }
    return false;
  }
  
  uint64_t read(){
    auto val = counter.load();
    if(val == 0 && counter.compare_exchange_strong(val, is_zero | helped)) return 0;
    return (val & is_zero) ? 0 : val;
  }
};
Code
Diff
  • #include <string>
    #include <string_view>
    
    std::string reverse_string(std::string_view word){
      return {word.rbegin(), word.rend()};
    }
    • public class ReverseString {
    • public static String reverseString(String word) {
    • return new StringBuilder(word).reverse().toString();
    • }
    • #include <string>
    • #include <string_view>
    • std::string reverse_string(std::string_view word){
    • return {word.rbegin(), word.rend()};
    • }
Arrays

Can also be solved with two sets

Code
Diff
  • #include <vector>
    #include <unordered_set>
    #include <numeric>
    
    int unique_sum(const std::vector<int>& nums) {
      std::unordered_set<int> once;
      std::unordered_set<int> more_than_once;
      
      for(auto&& num : nums){
        if(once.find(num) == once.end() && more_than_once.find(num) == more_than_once.end()){
          once.insert(num);
        }
        else if(once.find(num) != once.end()){
          once.erase(num);
          more_than_once.insert(num);
        }
      }
      
      return std::reduce(once.cbegin(), once.cend(), 0);
    }
    • #include <iostream>
    • #include <vector>
    • #include <unordered_map>
    • #include <cassert>
    • #include <unordered_set>
    • #include <numeric>
    • int unique_sum(const std::vector<int>& nums) {
    • std::unordered_map<int, int> hashMap;
    • for (int i = 0; i < nums.size(); i++) {
    • if (hashMap.find(nums[i]) == hashMap.end()) {
    • hashMap[nums[i]] = nums[i];
    • } else {
    • hashMap[nums[i]] = 0;
    • std::unordered_set<int> once;
    • std::unordered_set<int> more_than_once;
    • for(auto&& num : nums){
    • if(once.find(num) == once.end() && more_than_once.find(num) == more_than_once.end()){
    • once.insert(num);
    • }
    • else if(once.find(num) != once.end()){
    • once.erase(num);
    • more_than_once.insert(num);
    • }
    • }
    • int sum = 0;
    • for (auto i: hashMap) {
    • sum = sum + hashMap[i.first];
    • }
    • return sum;
    • return std::reduce(once.cbegin(), once.cend(), 0);
    • }

why add, when we can do it our self.

Code
Diff
  • #include <bitset>
    #include <fmt/core.h>
    
    std::bitset<64> bitwiseAdd(std::bitset<64> x, std::bitset<64> y) {
        while ((x & y).any()) { 
            std::bitset<64> carry = (x & y) << 1;
            x = x ^ y;
            y = carry;
        }
        return x ^ y;
    }
    
    
    int64_t multiply(int32_t a, int32_t b) {
      std::bitset<64> bitsetA(static_cast<uint64_t>(a));
      std::bitset<64> bitsetB(static_cast<uint64_t>(b));
      std::bitset<64> result;
    
      for (int i = 0; i < 64; ++i) {
        if (bitsetB.test(i)) {
          auto shiftedA = (bitsetA << i);
          result = bitwiseAdd(result, shiftedA);
        }
      }
    
      return static_cast<int64_t>(result.to_ullong());
    }
    • int just_why(int a, int b) { return b ? a + just_why(a, b - 1) : 0; }
    • int multiply(int a, int b) { return just_why(a, b); }
    • #include <bitset>
    • #include <fmt/core.h>
    • std::bitset<64> bitwiseAdd(std::bitset<64> x, std::bitset<64> y) {
    • while ((x & y).any()) {
    • std::bitset<64> carry = (x & y) << 1;
    • x = x ^ y;
    • y = carry;
    • }
    • return x ^ y;
    • }
    • int64_t multiply(int32_t a, int32_t b) {
    • std::bitset<64> bitsetA(static_cast<uint64_t>(a));
    • std::bitset<64> bitsetB(static_cast<uint64_t>(b));
    • std::bitset<64> result;
    • for (int i = 0; i < 64; ++i) {
    • if (bitsetB.test(i)) {
    • auto shiftedA = (bitsetA << i);
    • result = bitwiseAdd(result, shiftedA);
    • }
    • }
    • return static_cast<int64_t>(result.to_ullong());
    • }
Fundamentals
Arrays
Strings

Might have cone a bit crazy with the tests, but hey now you should be able to pass any container that satisfy the requirement. And if it doesn't it wont compile.

Code
Diff
  • #include <string>
    #include <vector>
    #include <algorithm>
    
    template<typename Container>
    bool containsT_Rex(const Container &things){
      using ValueType = typename Container::value_type;
      static_assert(std::is_convertible_v<decltype(std::declval<ValueType>() == std::declval<std::string>()), bool>, "Container elements must be comparable to std::string");
      
      static constexpr auto trex = "Tyrannosaurus";
      return std::find(things.cbegin(), things.cend(), trex) != things.cend();
    }
    • public class findT_Rex {
    • public static boolean containsT_Rex(String[] things) {
    • //insert code!
    • return true;
    • }
    • #include <string>
    • #include <vector>
    • #include <algorithm>
    • template<typename Container>
    • bool containsT_Rex(const Container &things){
    • using ValueType = typename Container::value_type;
    • static_assert(std::is_convertible_v<decltype(std::declval<ValueType>() == std::declval<std::string>()), bool>, "Container elements must be comparable to std::string");
    • static constexpr auto trex = "Tyrannosaurus";
    • return std::find(things.cbegin(), things.cend(), trex) != things.cend();
    • }
Code
Diff
  • #include <type_traits>
    #include <limits>
    #include <bitset>
    
    template<typename T>
    constexpr bool is_more_than_2(T n){
      static_assert(std::is_integral_v<T>, "T must be an integral type.");
      
      constexpr size_t numBits = std::numeric_limits<T>::digits + std::is_signed_v<T>;
      std::bitset<numBits> bits(n);
      
      if constexpr (std::is_unsigned_v<T>) {
        // For unsigned, check if more than 1 bit is set
        return bits.count() > 1;
      } else {
        // For signed, ensure the sign bit is unset and more than 1 bit is set
        bool signBitUnset = !bits[numBits - 1];
        bits.reset(numBits - 1); // Mask out the sign bit
        return signBitUnset && bits.count() > 1;
      }
    }
    • def is_more_than_2(n):
    • return n > 2
    • #include <type_traits>
    • #include <limits>
    • #include <bitset>
    • template<typename T>
    • constexpr bool is_more_than_2(T n){
    • static_assert(std::is_integral_v<T>, "T must be an integral type.");
    • constexpr size_t numBits = std::numeric_limits<T>::digits + std::is_signed_v<T>;
    • std::bitset<numBits> bits(n);
    • if constexpr (std::is_unsigned_v<T>) {
    • // For unsigned, check if more than 1 bit is set
    • return bits.count() > 1;
    • } else {
    • // For signed, ensure the sign bit is unset and more than 1 bit is set
    • bool signBitUnset = !bits[numBits - 1];
    • bits.reset(numBits - 1); // Mask out the sign bit
    • return signBitUnset && bits.count() > 1;
    • }
    • }

Checked math in c++, using some buildins for gcc/clang. Translated from Rust.
Can be made without the buildins, but you would have to make your own boundary checks.

Code
Diff
  • #include <optional>
    #include <limits>
    
    std::optional<int32_t> add_checked(int32_t a, int32_t b){
      int32_t r{};
      if(!__builtin_sadd_overflow(a, b, &r)){
        return r;
      }
      
      return std::nullopt;
    }
    
    std::optional<int32_t> sub_checked(int32_t a, int32_t b){
      int32_t r{};
      if(!__builtin_ssub_overflow(a, b, &r)){
        return r;
      }
      
      return std::nullopt;
    }
    
    std::optional<int32_t> mul_checked(int32_t a, int32_t b){
      int32_t r{};
      if(!__builtin_smul_overflow(a, b, &r)){
        return r;
      }
      
      return std::nullopt;
    }
    
    std::optional<int32_t> div_checked(int32_t a, int32_t b){
      if(b == 0 || (a ==  std::numeric_limits<int32_t>::min() && b == -1)){
        return std::nullopt;
      }
      return a / b;
    }
    
    std::optional<int32_t> mod_checked(int32_t a, int32_t b){
      if(b == 0 || (a ==  std::numeric_limits<int32_t>::min() && b == -1)){
        return std::nullopt;
      }
      return a % b;
    }
    
    std::optional<int32_t> calculator(Operation op, int32_t x, int32_t y) {
      switch(op){
          case Operation::Add:return add_checked(x, y);
          case Operation::Subtract: return sub_checked(x, y);
          case Operation::Multiply: return mul_checked(x, y);
          case Operation::Divide: return div_checked(x, y);
          case Operation::Modulo: return mod_checked(x, y);
          default:
          return std::nullopt;
      }
    }
    • mod preloaded;
    • use preloaded::Operation;
    • #include <optional>
    • #include <limits>
    • fn calculator(op: Operation, x: i32, y: i32) -> Option<i32> {
    • match op {
    • Operation::Add => x.checked_add(y),
    • Operation::Subtract => x.checked_sub(y),
    • Operation::Multiply => x.checked_mul(y),
    • Operation::Divide => x.checked_div(y),
    • Operation::Modulo => x.checked_rem(y)
    • }
    • std::optional<int32_t> add_checked(int32_t a, int32_t b){
    • int32_t r{};
    • if(!__builtin_sadd_overflow(a, b, &r)){
    • return r;
    • }
    • return std::nullopt;
    • }
    • std::optional<int32_t> sub_checked(int32_t a, int32_t b){
    • int32_t r{};
    • if(!__builtin_ssub_overflow(a, b, &r)){
    • return r;
    • }
    • return std::nullopt;
    • }
    • std::optional<int32_t> mul_checked(int32_t a, int32_t b){
    • int32_t r{};
    • if(!__builtin_smul_overflow(a, b, &r)){
    • return r;
    • }
    • return std::nullopt;
    • }
    • std::optional<int32_t> div_checked(int32_t a, int32_t b){
    • if(b == 0 || (a == std::numeric_limits<int32_t>::min() && b == -1)){
    • return std::nullopt;
    • }
    • return a / b;
    • }
    • std::optional<int32_t> mod_checked(int32_t a, int32_t b){
    • if(b == 0 || (a == std::numeric_limits<int32_t>::min() && b == -1)){
    • return std::nullopt;
    • }
    • return a % b;
    • }
    • std::optional<int32_t> calculator(Operation op, int32_t x, int32_t y) {
    • switch(op){
    • case Operation::Add:return add_checked(x, y);
    • case Operation::Subtract: return sub_checked(x, y);
    • case Operation::Multiply: return mul_checked(x, y);
    • case Operation::Divide: return div_checked(x, y);
    • case Operation::Modulo: return mod_checked(x, y);
    • default:
    • return std::nullopt;
    • }
    • }
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{});
    • }
    • }