Skip to content

Instantly share code, notes, and snippets.

@marimeireles
Created March 11, 2021 12:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marimeireles/bc6680694ba2f7c924ac69f9d186b12e to your computer and use it in GitHub Desktop.
Save marimeireles/bc6680694ba2f7c924ac69f9d186b12e to your computer and use it in GitHub Desktop.
# How to use templates (without using templates)
## Span:
### Substituting templates
You can use std::span. It allows you to create constraints over your templates. It's more or less the same use. It's faster than templating and with more strict data.
### Cutting vectors
const auto vec = std:vector{1,2,3,4,5,6,7}
mean(vec | drop(2) | drop_last(2)) is the same as mean({vec.begin() + 2, vec.end() -2}) and same as std::span(vec) | stride(2)
### Pitfalls
You can put vectors inside spans, I don't know why you'd do that. Remember that if stuff in span is encapsulating a non const value, it will be non const even if your span is const. You can specify the type of what's inside the span. std::span<const int>(vec)
## Variants
A variant is a type safe union.
An union is something that is the size of its biggest member.
```
union types
{
short a;
int b;
double c;
}
auto t = types()
t.b = 4;
//assignment is fine
t.c = 5.0;
//fine
std::cout << t.b; //undefined behavior
```
You have to write code around to be able to access the types.
Variants allow you to do this automatically and safely.
std::monostate is an alternative to return an empty solution.
std::holds_alternative allows you to check which type is active, I think (I need to check her slides to see how to use it properly)
You can call visit with variant. (She also has good examples with this in her slides)
A visit expects a visitor function that expects every possible type of a variant.
### Any
It's a safer substitute to the void* type. It holds the address of any other object, it cannot be dereferrence, it has to be casted, the cast only works correctly if you know the cast you should use, which may cause you to cast to the wrong type causing weird behaviour, it doesn't control life times, causing memory leaks.
```
std::any my = "yo";
my = 2.0;
```
It will manage lifetime by itself.
You can find out the type by doing `my.type().name()`, so the type can be obtained in runtime type. Which can cause performance issues if you have to keep testing for it all the time.
If you cast it to a wrong type it will throw an exception.
You can reset it to an empty state with `my.reset()`.
### Use cases
It's a property class that can hold any type.
Only use `any` if you don't have other choices, otherwise is better to use `variant`.
## Function
A high order function is a function that accepts a callable (which may manipulate the data).
```
template <typename Func>
auto filter_and_do_stuff(const std::vector<souble& data, const Func& condition)
{
for (const auto element : data)
{
if (condition(element))
{
std::cout << element;
//do stuff
}
}
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment