#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&
withstd::string_view
to reduce the number of the string allocations. -
Replaced
std::vector<>.push_back()
withstd::vector<>.emplace_back()
to construct the string directly while inserting and to prevent copies.
#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.
#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;
- }
- }
// 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.
#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{});
- }
- }