<commit_before>= C++ questions
:toc: macro

toc::[]

== les operations < 

Intéret de definir un operateur externe

  Type c = 1 + Type(2);

== conversions implicites (from et to)

 class B {
   public:
  // conversion from A (constructor):
  B (const A& x) {}
  // conversion to A (type-cast operator)
  operator A() {return A();}
  };

* std::map, insert versus []. 
** le [] est moins efficace, passe par le contructeur par défaut puis initie la valeur
** Le insert permet de savoir si une nouvelle valeur a été insérée.


== constructeur/destructeur

=== rule of three
 
Si on doit définir soit le destructeur, ou le constructeur par copie ou 'opérateur d'assignation c'est qu'on doit définir les 3. On doit gérer les ressources différemment de l'implem par défaut.

** peut jeter des exceptions
** ne doit pas appeler de fonction virtuelle
** un destructeur est virtuel
** ne doit *pas* jeter d'exception. Pourrait déclencher plusieurs exceptions lors de l'unstacking)

== volatile
----
static int foo;

void bar(void) {
    foo = 0;

    while (foo != 255)
         ;
}
----
La variable peut être modifiée par un thread => on empêche les optimisations.

* std::function

encapsule n'importe quel type de fonction (membre, lambda, ...)

    std::function<void(const Foo&, int)> f_add_display =      &Foo::print_add;
    Foo foo(314159);
    f_add_display(foo, 1);
    
== type traits/policy traits

  template<> 
  struct algorithm_selector< true > { 
    template< typename T > 
    static void implementation( T& object )   { 
      object.optimised_implementation(); 
    } 
  };

  template< typename T > 
  void algorithm( T& object ) { 
    algorithm_selector< supports_optimised_implementation< T >::value >::implementation(object); 
  }
  
  template<> 
  struct 
     supports_optimised_implementation< ObjectB > { 
        static const bool value = true; 
  };
  
== rvalue reference


std::move: renvoie une rvalue, c'est juste un cast en rvalue. Le contenu est rendu volable via le move constructor ou le move assignement operator

2 opérations ajoutées:

* move constructor
* move assignment operator
Certains types sont non copyables mais movable (unique_ptr, thread, fstream). On peut trier des vecteurs<unique_ptr<A>>

* rvalue reference<commit_msg>Update 2016-01-13-C-questions.adoc<commit_after>= C++ questions
:toc: macro
:language: c++

toc::[]


== les operations < 

Intéret de definir un operateur externe

  Type c = 1 + Type(2);

== conversions implicites (from et to)

[source]
----
class B {
public:
  // conversion from A (constructor):
  B (const A& x) {}
  // conversion to A (type-cast operator)
  operator A() {return A();}
};
----

* std::map, insert versus []. 
** le [] est moins efficace, passe par le contructeur par défaut puis initie la valeur
** Le insert permet de savoir si une nouvelle valeur a été insérée.


== constructeur/destructeur

=== rule of three
 
Si on doit définir soit le destructeur, ou le constructeur par copie ou 'opérateur d'assignation c'est qu'on doit définir les 3. On doit gérer les ressources différemment de l'implem par défaut.

** peut jeter des exceptions
** ne doit pas appeler de fonction virtuelle
** un destructeur est virtuel
** ne doit *pas* jeter d'exception. Pourrait déclencher plusieurs exceptions lors de l'unstacking)

== volatile

[source]
----
static int foo;

void bar(void) {
    foo = 0;

    while (foo != 255)
         ;
}
----
La variable peut être modifiée par un thread => on empêche les optimisations.

* std::function

encapsule n'importe quel type de fonction (membre, lambda, ...)

    std::function<void(const Foo&, int)> f_add_display =      &Foo::print_add;
    Foo foo(314159);
    f_add_display(foo, 1);
    
== type traits/policy traits

[source]
----
template<> 
struct algorithm_selector< true > { 
    template< typename T > 
    static void implementation( T& object )   { 
      object.optimised_implementation(); 
    } 
};

template< typename T > 
void algorithm( T& object ) { 
  algorithm_selector< supports_optimised_implementation< T >::value >::implementation(object); 
}
  
template<> 
struct 
   supports_optimised_implementation< ObjectB > { 
      static const bool value = true; 
};
  
== rvalue reference


std::move: renvoie une rvalue, c'est juste un cast en rvalue. Le contenu est rendu volable via le move constructor ou le move assignement operator

2 opérations ajoutées:

* move constructor
* move assignment operator
Certains types sont non copyables mais movable (unique_ptr, thread, fstream). On peut trier des vecteurs<unique_ptr<A>>

* rvalue reference
{'fraction_non_alphanumeric': 0.1008714596949891, 'fraction_numerical': 0.008278867102396514, 'mean_word_length': 3.60481444332999, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '953218', 'n_tokens_mistral': 1501, 'n_tokens_neox': 1400, 'n_words': 531}