Ad
Code
Diff
  • #include <string>
    #include <vector>
    #include <string_view>
    
    auto split(std::string_view str, char sep) {
      std::vector<std::string> result;
      std::size_t pos = 0, pos2 = 0;
      
      while ((pos2 = str.find(sep, pos)) != std::string::npos) {
        result.emplace_back(str.substr(pos, pos2 - pos));
        pos = pos2 + 1;
      }
      result.emplace_back(str.substr(pos));
      
      return result;
    }
    
    
    • #include <string>
    • #include <vector>
    • #include <string_view>
    • auto split(const std::string& str, char sep) {
    • auto result = std::vector<std::string>{};
    • std::string::size_type pos = 0, pos2 = 0;
    • auto split(std::string_view str, char sep) {
    • std::vector<std::string> result;
    • std::size_t pos = 0, pos2 = 0;
    • while ((pos2 = str.find(sep, pos)) != std::string::npos) {
    • result.push_back(str.substr(pos, pos2 - pos));
    • result.emplace_back(str.substr(pos, pos2 - pos));
    • pos = pos2 + 1;
    • }
    • result.push_back(str.substr(pos));
    • result.emplace_back(str.substr(pos));
    • return result;
    • }

Changes:

  • Replaced const std::string& with std::string_view to reduce the number of the string allocations.

  • Replaced std::vector<>.push_back() with std::vector<>.emplace_back() to construct the string directly while inserting and to prevent copies.

Code
Diff
  • #include <string>
    #include <vector>
    #include <string_view>
    
    using std::string;
    using std::vector;
    
    vector<string> split(std::string_view str, char sep, bool strip = true)
    {
      vector<string> result;
      string buf;
      
      for (char c : str) {
        if (c == sep) {
          if (!strip || !buf.empty()) {
            result.emplace_back(buf);
            buf.clear();
          }
        } else buf.push_back(c);
      }
      if (!strip || !buf.empty()) result.emplace_back(buf);
      
      return result;
    }
    
    
    • #include <string>
    • #include <vector>
    • #include <string_view>
    • using std::string;
    • using std::vector;
    • vector<string> split(const string& str, char sep, bool strip = true) {
    • vector<string> split(std::string_view str, char sep, bool strip = true)
    • {
    • vector<string> result;
    • string buf;
    • for (char c : str) {
    • if (c == sep) {
    • if (!strip || !buf.empty()) {
    • result.push_back(buf);
    • result.emplace_back(buf);
    • buf.clear();
    • }
    • } else buf.push_back(c);
    • }
    • if (!strip || !buf.empty()) result.push_back(buf);
    • if (!strip || !buf.empty()) result.emplace_back(buf);
    • return result;
    • }

Multiplies two numbers or any arithmetic-like types (bool, chars, etc.) using SFINAE to allow the function work only with arithmetic types. Also, it uses the decltype(auto) C++17 feature to deduce the return type.

Code
Diff
  • #include <utility>
    #include <type_traits>
    
    namespace
    {
      template<typename T, typename U, typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U>>>
      inline constexpr decltype(auto) multiply(T a, U b)
      {
        return a * b;
      }
    }
    • #include <utility>
    • #include <type_traits>
    • template<typename T, typename U>
    • constexpr auto multiply(T a, U b) -> decltype(std::declval<T>() * std::declval<U>()){
    • return a * b;
    • namespace
    • {
    • template<typename T, typename U, typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U>>>
    • inline constexpr decltype(auto) multiply(T a, U b)
    • {
    • return a * b;
    • }
    • }
Test Cases
Diff
  • // TODO: Replace examples and use TDD by writing your own tests
    
    Describe(any_group_name_you_want)
    {
        It(should_do_something)
        {
          int result = multiply(10, 2);
          Assert::That(result, Equals(20));
          
          Assert::That(multiply(10, 2.2f), Equals(22.0f));
          Assert::That(multiply(2.2f, 10), Equals(22.0f));
          Assert::That(multiply(10, 2.2), Equals(22.0));
          Assert::That(multiply(2.2, 10), Equals(22.0));
          // TODO Add more tests for bool, char, and everything that is arithmetic-like types
        }
    };
    
    • // TODO: Replace examples and use TDD by writing your own tests
    • Describe(any_group_name_you_want)
    • {
    • It(should_do_something)
    • {
    • int result = multiply(10,2);
    • Assert::That(result, Equals(20));
    • int result = multiply(10, 2);
    • Assert::That(result, Equals(20));
    • Assert::That(multiply(10, 2.2f), Equals(22.0f));
    • Assert::That(multiply(2.2f, 10), Equals(22.0f));
    • Assert::That(multiply(10, 2.2), Equals(22.0));
    • Assert::That(multiply(2.2, 10), Equals(22.0));
    • // TODO Add more tests for bool, char, and everything that is arithmetic-like types
    • }
    • };

This algorithm of 'sum()' is SFINAE-friendly. By first testing if the corresponding types can be added with the type trait 'has_plus' because some types doesn't have the 'operator+' defined. If for any reason, the types doesn't have the addition operator available, the function will be disabled via 'std::enable_if' and will be discarded by SFINAE. In constrast, if the types can be added, the 'std::enable_if' trait will enable the function and returning the corresponding type of add the two types with the 'plus_result' trait.

Code
Diff
  • #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 <vector>
    • #include <numeric>
    • #include <type_traits>
    • #include <utility>
    • template <typename T> using add_t=decltype(T() + T());
    • namespace
    • {
    • template<typename, typename, typename = void>
    • struct has_plus : std::false_type {};
    • template <typename T = double>
    • add_t<T> sum(const std::vector<T>& v) {
    • return std::accumulate(v.cbegin(),v.cend(),add_t<T>{0});
    • 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{});
    • }
    • }