Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

39

description

Le C++ a vécu un tel renouveau ces dernières années avec la publication de C++11 (et l'arrivée imminente de C++14) que l'on peut dire qu'il y a une rupture, un avant et un après. Ce changement dans le style de programmation transparait dans chaque ligne de code et se reconnait du premier coup d’œil. À chaque nouvelle version, Visual C++ se rapproche un peu plus du support de la norme, permettant d'écrire du code plus lisible, plus robuste et plus rapide. Plus qu'un simple catalogue des fonctionnalités du langage prises en compte par Visual C++2013, cette présentation a pour ambition de vous montrer, par des exemples concrets, quels bénéfices vous pouvez tirer du C++ moderne. Au détour de ces exemples, on mettra en œuvre la sémantique de déplacement, les fonctions par défaut ou interdites, l'initialisation uniforme, les alias de types... en démasquant quelques pièges à éviter, mais surtout en présentant des pratiques sur lesquels s'appuyer pour apprivoiser ce langage moderne qu'est le C++. On fera enfin un petit point sur l'état d'avancement de Visual C++ par rapport à la norme, et sur la feuille de route présentée par les équipes de développement de Visual C++. Speakers : Christophe Pichaud (Sogeti), Loïc Joly (Cast)

Transcript of Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Page 1: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
Page 2: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++

Bonnes pratiques C++11

avec Visual C++Loïc Joly - CAST

Christophe Pichaud - Sogeti

www.castsoftware.com

www.fr.sogeti.com

Page 3: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Depuis votre smartphone sur :

http://notes.mstechdays.fr

De nombreux lots à gagner toute les heures !!!

Claviers, souris et jeux Microsoft…

Merci de nous aider à améliorer les Techdays !

Donnez votre avis !

Page 4: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

PLANVisual C++ 2013

November 2013 CTP

Guide de survie en C++11

Interop WinRT

Page 6: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• CTP = version beta. Installable sans danger.

• C++ 11– Génération des fonctions spéciales de déplacement, & and && for *this

– Initialisation thread safe des variables statiques

– Inheriting constructors

– alignof/alignas, __func__, Extended sizeof

– constexpr (partiel : Pas les fonctions membre)

– noexcept (partiel : Pas la version conditionelle)

• C++14– decltype(auto), auto function return type deduction

– generic lambdas (partiel : Liste de capture explicite uniquement)

• Autre– Resumable functions and await

November 2013 CTP

Page 7: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

GUIDE DE SURVIE EN C++11

Autour de la sémantique de déplacement

Page 8: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Copie

• La destination vaut la valeur

qu’avait la source initialement

• La source est inchangée

• On peut continuer à utiliser la

source

• Fournit la strong exception

guarantee

• Plus lent

Déplacement

• La destination vaut la valeur qu’avait la source initialement

• On se moque de l’état de la source, tant qu’il est viable

• On va éviter d’utiliser la source par la suite

• Ne fournit que la basic exception guarantee

• …mais peut souvent être noexcept

• Plus rapide

Intérêt de déplacer

Page 9: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Lvalue (ça possède un nom, on peut en prendre

l’adresse) et Rvalue (le reste)

• On peut surcharger une fonction là-dessus– int f(maClasses const &c); // Version pour les Lvalues

– int f(maClasses &&c); // Version pour les Rvalues

• Dans la seconde version, comme on sait qu’on est les

seuls à accéder à l’objet, on a le droit d’être destructif

Comment ça marche ?

Page 10: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Constructeur et affectation par déplacement

– MaClasse(MaClasse &&c);

– MaClasse &operator=(MaClasse &&c);

• Pas générés automatiquement si un destructeur ou constructeur de

copie est défini

• Empêche la génération automatique d’un constructeur de copie

• Règle des 5 (ou règle des 0 !)

Comment rendre nos classes déplaçables

Page 11: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Si possible, rendre les opérations de déplacement noexcept, et le

déclarer

– Utiliser une macro en attendant un meilleur support de VC++

• Réfléchir à l’état d’un objet depuis lequel il y a eu déplacement

• Préférez la règle des 0 à la règle des 5

– Utiliser des classes RAII pour gérer vos données, comme

[shared/unique]_ptr

– Éviter new et delete !

Quelques conseils sur les classes

déplaçables

Page 12: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

1. Un type à sémantique de valeur (string, vector, map,

optional…)

2. Des pointeurs à propriété unique (unique_ptr / T*

observant (observer_ptr ?)

3. Des pointeurs à propriété partagée

(shared_ptr/weak_ptr)

Utiliser dans l’ordre de préférence

Page 13: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Notion pédagogique inventée pas Scott Meyers

• T&& dans un contexte où T est déduit Universal reference

• Selon la manière dont on instanciera, une universal reference

deviendra :

– Une Lvalue reference si T est une Lvalue

– Une Rvalue reference si T est une Rvalue

• Idéal pour transmettre des arguments à l’aide de std::forward

• On n’a pas forcément le droit de toucher à la source !

• Fonctionne souvent assez mal avec la surcharge (car peut déjà tout

prendre en charge)

Universal references

Page 14: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

La fonction va : On utilise : Et pour transmettre:

Utiliser la donnée

Ex: ofstream::open

void f(T const &t);ouvoid f(T &t);

g(t)

Dupliquer la donnée

Ex: vector::push_back

void f(T t); g(std::move(t))

void f(T const &t); void f(T&& t);

g(t)g(std::move(t))

Transmettre une donnée

dont on ne sait rien

Ex: make_shared

template <class T>void f(T &&t);

g(std::forward<T>(t))

Transmettre des arguments

Page 15: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Et avec des pointeurs intelligents ?Pour Utiliser

Une fonction manipulant uniquement

l’objet pointé

void f(T& t);

void f(T *t); // Si l’objet peut ne pas

exister

void f(observer_ptr<T> t); // au lieu de

T* ?

Une fonction prenant propriété d’un

objet géré par shared_ptr

void f(shared_ptr<T> t);

Une fonction prenant la propriété

unique d’un objet géré par pointeur

void f(unique_ptr<T> t);

Le reste Plus rare…

Page 16: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

INTEROP WINRT

Page 17: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Conception de composants WinRT

C# / VB C++/CXC++ avec

WRL

Page 18: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Pourquoi faire des composants WinRT en C++

PerformanceGestionbatterie

Protection contre la

décompilation

Accès à Win32

Code existant

Page 19: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Scénarios d’applications C++ hybrides

Interface HTML/JS

Composants

WinRT C++

Interface C#/VB

ComposantsWinRT C++

InterfaceC++

ComposantsWinRT C#/VB

Page 20: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Windows 8 utilise des composants COM– il existe l’interface IUnknown

– mais aussi IInspectable

• Ces composants COM sont nommés WinRT

• Il existe deux manières de coder– C++/CX qui sont des extensions du compilateur

– C++ Standard avec WRL : Windows Runtime Library

• WRL est inspirée de la librairie ATL

Le nouveau modèle de composants WinRT

Page 21: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• C’est un composant COM

• Il expose des metadata (.winmd)

• Il utilise les types Windows spécifiques

• Link avec RuntimeObject.lib

• Ne tourne que sous Windows 8.x– *En mode Desktop

– En mode Store App

Un composant WinRT

Page 22: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Les entêtes sont définies dans– C:\Program Files (x86)\Windows Kits\8.1\Include\winrt\wrl

• async.h

• client.h

• def.h

• event.h

• ftm.h

• implements.h

• internal.h

• module.h

• wrappers\corewrappers.h

La librairie WRL

Page 23: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

#include "Library1_h.h"

namespace ABI { namespace Library1 {

class Logger : public RuntimeClass<ILogger>

{

InspectableClass(L"Library1.Logger",

BaseTrust)

public:

STDMETHOD(get_Name)(HSTRING* value);

STDMETHOD(put_Name)(HSTRING value);

STDMETHOD(LogInfo)(HSTRING value);

STDMETHOD(GetInt32)(int * pValue);

private:

std::wstring name;

};

ActivatableClass(Logger);

}

}

Un composant WRL Simpleimport "inspectable.idl";

import "Windows.Foundation.idl";

#define COMPONENT_VERSION 1.0

namespace Library1 {

interface ILogger;

runtimeclass Logger;

[uuid(3EC4B4D6-14A6-4D0D-BB96-31DA25224A15),

version(COMPONENT_VERSION)]

interface ILogger : Iinspectable

{

[propget] HRESULT Name([out, retval] HSTRING* value);

[propput] HRESULT Name([in] HSTRING value);

HRESULT LogInfo([in] HSTRING value);

HRESULT GetInt32([out] int * pValue);

}

[version(COMPONENT_VERSION),

activatable(COMPONENT_VERSION)]

runtimeclass Logger

{

[default] interface ILogger;

}

}

Page 24: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

#include "Library1_h.h"

class Logger :

public

RuntimeClass<RuntimeClassFlags<ClassicCom>,

ILogger>

{

public:

STDMETHOD(LogInfo)(BSTR value);

};

Un composant COM WRL import "ocidl.idl";

#define COMPONENT_VERSION 1.0

[uuid(3AAF07AA-A699-4E7C-8F01-BFF237D22B1B),

version(COMPONENT_VERSION)]

interface ILogger : IUnknown

{

HRESULT LogInfo([in] BSTR bstrMessage);

}

[uuid(F15D3912-E8B8-40C8-8CF3-354F0B8B93CC),

version(COMPONENT_VERSION)]

library WRLCOMLibrary1

{

[uuid(75DB8F5A-F13F-4E16-A487-9CD26A874654),

version(COMPONENT_VERSION)]

coclass Logger

{

[default] interface ILogger;

}

}

Page 25: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Attention WRL ne fournit pas de support pour– IDispatch et les interfaces dual, les connections points

– L’enregistrement automatique du module

• Il faut le faire manuellement avec un .reg

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{75DB8F5A-F13F-4E16-A487-9CD26A874654}]

@="Logger Class"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{75DB8F5A-F13F-4E16-A487-9CD26A874654}\InprocServer32]

@="C:\\dev\\Store\\App1\\Debug\\WRLCOMLibrary1Dll.dll"

"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{75DB8F5A-F13F-4E16-A487-9CD26A874654}\Programmable]

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{75DB8F5A-F13F-4E16-A487-9CD26A874654}\TypeLib]

@="{F15D3912-E8B8-40C8-8CF3-354F0B8B93CC}"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{75DB8F5A-F13F-4E16-A487-9CD26A874654}\Version]

@="1.0“

WRL et COM

Page 26: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Exemple de méthode dans la classe Root:

Windows.Foundation.IAsyncOperation<ILogger> GetLoggerAsync();

• Exemple de client XAML C#:

private async void Button_Click(object sender, RoutedEventArgs e)

{

Library1.Root root = new Root();

Library1.ILogger ilogger = await root.GetLoggerAsync();

ilogger.LogInfo("log me !");

}

WRL et les méthodes Async

Page 27: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

interface IRoot;

runtimeclass Root;

[uuid(3EC4B4D6-14A6-4D0D-BB96-31DA25224A16), version(COMPONENT_VERSION)]

interface IRoot : IInspectable

{

HRESULT GetLoggerAsync([out][retval] Windows.Foundation.IAsyncOperation<ILogger*>** value);

}

[version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]

runtimeclass Root

{

[default] interface IRoot;

}

Un composant WRL et les méthodes Async

Page 28: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

#include "Library1_h.h"

namespace ABI { namespace Library1 {

class Root : public RuntimeClass<IRoot>

{

InspectableClass(L"Library1.Root", BaseTrust)

public:

STDMETHOD(GetLoggerAsync)(Windows::Foundation::IAsyncOperation<ILogger*>** value);

};

ActivatableClass(Logger);

}

}

• Il faut maintenant implémenter cette interface

• C:\Program Files (x86)\Windows Kits\8.1\Include\winrt

– windows.foundation.collections.h

Le composant WRL avec une méthode Async

Page 29: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

namespace ABI { namespace Library1 {

STDMETHODIMP Root::GetLoggerAsync(Windows::Foundation::IAsyncOperation<ILogger*>** value)

{

ComPtr<task_based_async_operation<ILogger>> pObject =

Make<task_based_async_operation<ILogger>>(

std::async([&]() -> ILogger*

{

ComPtr<Logger> p = Make<Logger>();

return p.Detach();

}));

*value = pObject.Detach();

return S_OK;

}

• La magie est contenue dans la classe task_based_async_operation via

PPL Tasks.

La routine GetLoggerAsync()

Page 30: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Exemple de méthode dans la classe Root:

Windows.Foundation.Collections::IVector<HSTRING> Getvector();

• Exemple de client XAML C#:

private async void Button_Click(object sender, RoutedEventArgs e)

{

Library1.Root root = new Root();

IList<string> list = root.GetVector();

foreach (string s in list) { … }

}

WRL et les Collections

Page 31: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

interface IRoot;

runtimeclass Root;

[uuid(3EC4B4D6-14A6-4D0D-BB96-31DA25224A16), version(COMPONENT_VERSION)]

interface IRoot : IInspectable

{

HRESULT GetVector([out][retval] Windows.Foundation.Collections.IVector<HSTRING>** value);

}

[version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]

runtimeclass Root

{

[default] interface IRoot;

}

Un composant WRL et les collections

Page 32: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

#include "Library1_h.h"

namespace ABI { namespace Library1 {

class Root : public RuntimeClass<IRoot>

{

InspectableClass(L"Library1.Root", BaseTrust)

public:

STDMETHOD(GetVector)(Windows::Foundation::Collections::IVector<HSTRING>** value);

};

ActivatableClass(Logger);

}

}

• Il faut maintenant implémenter cette interface

• C:\Program Files (x86)\Windows Kits\8.1\Include\winrt

– windows.foundation.collections.h

Le composant WRL avec les collections

Page 33: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

namespace ABI { namespace Library1 {STDMETHODIMP Root::GetVector(Windows::Foundation::Collections::IVector<HSTRING>** value)

{

ComPtr<Vector<HSTRING>> v = Make<Vector<HSTRING>>();

HString str;

str.Set(L"String1");

v->Append(str.Detach());

str.Set(L"String2");

v->Append(str.Detach());

str.Set(L"String3");

v->Append(str.Detach());

*value = v.Detach();

return S_OK;

}

• La magie est contenue dans la classe Vector via std::vector<T>.

La routine GetVector()

Page 34: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

• Support en C++/CX via les ‘PPL Taks’

IAsyncOperation<int>^ CalculateAnswer() {

return concurrency::create_async([]() -> int {

// faire une opération longue ici…

return 42; }); }

IAsyncOperation<String^>^ CalculateQuestion() {

return create_async([]() -> String^ {

// faire une opération longue ici…

return ref new String(L“Hello IAsyncOperation<T>…"); }); }

WRL et les opérations asynchrones

Page 35: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

CONCLUSION

Page 36: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Juin 2013

Page 37: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

C/C++ French user group : [email protected]

Page 38: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Développement C++#mstechdays

Page 39: Bonnes pratiques pour apprivoiser le C++11 avec Visual C++

Digital is

business