|
std::string_view | trim_whitespace (const std::string_view path) |
| Remove leading and trailing whitespace. More...
|
|
| TEST (cpp11, trim_whitespace) |
|
std::string | remove_control_characters (const std::string_view str) |
| Remove non-printable characters. More...
|
|
| TEST (cpp20, remove_control_characters) |
|
constexpr std::string | transform_view (const std::string str, const auto func) |
| Helper routine to transform a string with a function. More...
|
|
constexpr char | toggle_case (const char c, const bool to_upper) |
| Toggle case. More...
|
|
constexpr char | toupper (const char c) |
| constexpr version of std::toupper More...
|
|
constexpr char | tolower (const char c) |
| constexpr version of std::tolower More...
|
|
| TEST (cpp11, case_tests_common) |
|
constexpr std::string | to_lowercase (const std::string str) |
| Use the lower case. More...
|
|
constexpr std::string | to_uppercase (const std::string str) |
| Use the upper case. More...
|
|
constexpr std::string | to_snakecase (const std::string str) |
| Use the Python case. More...
|
|
| TEST (cpp11, case_tests1) |
|
| TEST (cpp11, case_tests2) |
|
std::string | get_file_name (const std::string_view path) |
| You can aslo break down a path using C++17's std::filesystem. More...
|
|
std::string | get_file_extension (const std::string_view path) |
|
std::string | get_stem (const std::string_view path) |
|
| TEST (cpp17, filename_operations) |
|
std::vector< std::string > | split_string (std::string_view sentence) |
|
| TEST (cpp20, split_string) |
|
| TEST (cpp20, check_substrings) |
|
| TEST (cpp11, range_based_for_loops) |
|
| TEST (cpp11, classes_and_type_traits) |
|
| TEST (cpp11, auto_type) |
|
| TEST (cpp11, lambda_expressions) |
|
| TEST (cpp11, exceptions) |
|
| TEST (cpp11, brace_initialisers) |
|
| TEST (cpp11, narrowing) |
|
| TEST (cpp11, learn_the_standard_library) |
|
| TEST (cpp11, threading) |
|
| TEST (cpp14, return_value_optimisation) |
|
| TEST (cpp14, digit_separators) |
|
| TEST (cpp17, optional_types) |
|
| TEST (cpp17, heterogeneous_types) |
|
| TEST (cpp17, filesystem) |
|
| TEST (cpp17, parallel_execution_policy) |
|
| TEST (cpp17, clamp_values) |
|
| TEST (cpp17, compiler_attributes) |
|
| TEST (cpp17, maybe_unused_attribute) |
|
| TEST (cpp20, ranges_and_views) |
|
| TEST (cpp20, reduce_and_accumulate) |
|
| TEST (cpp20, deprecated_with_comment) |
|
| TEST (cpp20, contains_for_associative_containers) |
|
TEST |
( |
cpp11 |
, |
|
|
classes_and_type_traits |
|
|
) |
| |
Not a modern feature, of course, but you should: make everything constant. You ought to be prefixing const as a matter of course and then removing it when you have to: it’s much easier to reason about code when the data are immutable. In an ideal world everything would be constant – like Haskell – but it’s a balance of reason and getting things done.
Knowning that classes sometimes need a virtual destructor always seemed a bit nuanced and error prone. Now you can test it.
Not my rules but a common opinion: structs hold data; but if there's any funtionality, then it should probably be a class.
Definition at line 380 of file test.cxx.
TEST |
( |
cpp11 |
, |
|
|
range_based_for_loops |
|
|
) |
| |
I really find it painful to go back to old style for-loops. All those clumsy explicit iterator declarations can be cleaned up beautifully with auto
; in fact, we can drop the iterators altogether and avoid that weird i dereferencing idiom. Note you don't have access to the current index (until C++2a), which isn't necessarily a bad thing if you have aspirations of parallelisation.
You can also pass a function object where you would a lambda to std::for_each, and do more complex things like store state between element But this does, of course, make parallelising the operation more complicated.
Definition at line 266 of file test.cxx.
TEST |
( |
cpp11 |
, |
|
|
threading |
|
|
) |
| |
Threading gives you the promise of speed at the expense of reasoning, complexity and debugging. But they are much more intuitive now than the old POSIX library.
std::futures are particularly interesting and let you return the stuff you're interested in much more easily: define a routine as a lambda and run it in the background while the main routine gets on with something else; and when we're ready, we block to get the value.
std::async runs the function anchronously (potentially in a separate thread which might be a part of a thread pool) and returns a std::future that will eventually hold the result of that function call.
std::launch::async: the task is executed on a different thread, potentially by creating and launching it first
std::launch::deferred: the task is executed on the calling thread the first time its result is requested (lazy evaluation)
Listen very carefully, I shall say this only once... if you get this reference then you are a senior dev. You can call things only once using statics and lambdas (IIFE); or, use the well-named Standard Library function.
Definition at line 584 of file test.cxx.