Transcript
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


Recommended