Excerpt from Aerix Consulting
Study notes:
1. Function Interface Design
Is my function? :
Movable Types:
3. Module
Ode To Function Objects:
Study notes:
1. Function Interface Design
Is my function? :
- easy to call correctly?
- hard to call incorrectly?
- efficient to call?
- with minimal copying?
- with minimal aliasing?
- without unnecessary resource allocation?
- easily composable with other functions?
- usable in higher-order constructs?
What’s the best way of getting data into and out of a function?
- Input Argument Categories
- Read-only: value is only ever read from, never modified or stored
- const l-ref (except small ones)
- Sink: value is consumed, stored, or mutated locally
- Goal: Avoid unnecessary copies, allow temporaries to be moved in.
- const l-ref and copy it into local variable
- r-ref. Take the r-value into function.
- What if the function takes more than 1 sink argument?
- Take sink arguments by value.
Since if passing in r-value, the r-value will be created as the l-value argument.
No extra copy constructor call needed. (extra reference: WANT SPEED? DON’T (ALWAYS) PASS BY VALUE.) - Eric Niebler : Out Parameters, Move Semantics, and Stateful Algorithms
- Encapsulate an algorithm’s state in an object that implements the algorithm.
2. Class Design
Can my type be…?:
Can my type be…?:
- …copied and assigned?
- …efficiently passed and returned?
- …efficiently inserted into a vector?
- …sorted?
- …used in a map? An unordered_map?
- …iterated over (if it’s a collection)?
- …streamed?
- …used to declare global constants?
- Regular Types
- Reference:
- rules of three:
- Basically, int-like types.
- Copyable, default constructable, assignable, equality-comparable, swappable, order-able
- They let us reason mathematically
- The STL containers and algorithms assume regularity in many places
- Make your types regular (if possible)
- **Make your types’ move operations noexcept (if possible)
- Q: Is my type Regular?
A: Check it at compile time!
template<typename T>
struct is_regular
: std::integral_constant< bool,
std::is_default_constructible<T>::value &&
std::is_copy_constructible<T>::value &&
std::is_move_constructible<T>::value &&
std::is_copy_assignable<T>::value &&
std::is_move_assignable<T>::value >
{};
struct T {};
static_assert(is_regular<T>::value, "huh?");
Movable Types:
- The moved-from state must be part of a class’s invariant.
- If above doesn’t make sense, the type isn’t movable.
- Every movable type must have a cheap(er)-to-construct, valid default state.
3. Module
Think:
- In C++11, what support is there for…
- … enforcing acyclic, hierarchical physical component dependencies?
- … decomposing large components into smaller ones?
- … achieving extensibility of components?
- … versioning (source & binary) components?
New library version with interface-breaking changes:
- Put all interface elements in a versioning namespace from day one
- Make the current version namespace inline
Name Hijacking: Unintentional ADL finds the wrong overload:
- template arguments are participating ADL.
ADL:
If the class is a class template instantiation, then the types of the template type arguments and the classes and namespaces in which the template template arguments are declared are also included.
Solution:
If the class is a class template instantiation, then the types of the template type arguments and the classes and namespaces in which the template template arguments are declared are also included.
Solution:
1. Use a non-inline ADL-blocking namespace
2. Use global function objects instead of free functions(i.e: Global function object, aka. functor)
template<typename T> struct lexical_cast_fn
{
template<typename U> T operator()(U const &u) const
{ //... }
};
template<typename T> constexpr lexical_cast_fn<T> lexical_cast{};
int main()
{
lexical_cast<int>("42");
}
Ode To Function Objects:
- They are never found by ADL!
- If phase 1 lookup finds an object instead of a function, ADL is disabled!
- They are first class objects
- Easy to bind
- Easy to pass to higher-order functions like std::accumulate
Guideline:
- Put type definitions in an ADL-blocking (non-inline!)
namespaces and export then with a using declaration, or… - Prefer global constexpr function objects over named free functions (except for documented customization points)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.