SlideShare ist ein Scribd-Unternehmen logo
1 von 67
Downloaden Sie, um offline zu lesen
Evolution of C++ Class Design
Mariusz Łapiński
2
3
More Effective C++
35 New Ways to Improve Your Programs and Designs
1995
4
Framework Design Guidelines
Conventions, Idioms, and Patterns
for Reusable .NET Libraries
2008
5
class VPtrBase
{
private:
bool destructible;
unsigned int nref;
bool share;
protected:
VPtrBase ();
VPtrBase (const VPtrBase& pb);
virtual ~VPtrBase () = 0;
public:
virtual VPtrBase* clone () const = 0;
VPtrBase* incRef (CloningBehaviourT cb = CB_ALLOW);
bool decRef ();
bool isDestructable () const;
bool isReferred () const;
bool isShared () const;
bool canShare () const;
void forbidDestruction ();
void allowDestruction ();
void forbidSharing ();
void allowSharing ();
void assign (const VPtrBase& pb);
};
6
class CObject
{
public:
virtual CRuntimeClass* GetRuntimeClass() const;
virtual ~CObject();
void* operator new(size_t nSize) throw(...);
...
BOOL IsSerializable() const;
BOOL IsKindOf(const CRuntimeClass* pClass) const;
virtual void Serialize(CArchive& ar);
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
...
};
Microsoft Foundation Classes
7
8
• The QObject class is the base class of all Qt objects.
• You can connect a signal to a slot with connect() and destroy the connection with
disconnect(). To avoid never ending notification loops you can temporarily block
signals with blockSignals(). The protected functions connectNotify() and
disconnectNotify() make it possible to track connections.
• QObjects organize themselves in object trees. When you create a QObject with
another object as parent, the object will automatically add itself to the parent's
children() list.
• Every object has an objectName() and its class name can be found via the
corresponding metaObject().
• Notice that the Q_OBJECT macro is mandatory for any object that implements signals,
slots or properties. You also need to run the Meta Object Compiler on the source file.
• Some QObject functions, e.g. children(), return a QObjectList. QObjectList is a
typedef for QList<QObject *>.
9
pthread_init(1);
POSIX Threads
10
// We need to call this to set up global state for TensorFlow.
tensorflow::port::InitMain(argv[0], &argc, &argv);
TensorFlow, Google
https://github.com/tensorflow/tensorflow
void InitMain(const char* usage, int* argc, char*** argv) {}
11
// Initialization
int mpiInitError = MPI_Init(argc, argv);
...
// Cleanup
MPI_Finalize();
MPI
12
// Initialization
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
...
// Cleanup
CoUninitialize();
COM
13
// Initialization
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
...
// Cleanup
GdiplusShutdown(gdiplusToken);
GDI+
14
BOOL WINAPI GetMessage(
_Out_ LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_ UINT wMsgFilterMin,
_In_ UINT wMsgFilterMax
);
WinAPI
15
// Initialization
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
...
// Cleanup
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
V8, Google
https://github.com/v8/v8
16
PassRegistry *Registry = PassRegistry::getPassRegistry();
initializeCore(*Registry);
initializeCodeGen(*Registry);
...
LLVM
https://github.com/llvm-mirror/llvm
void foo(Bar& bar) {
assert(&bar != nullptr); // Forewarned is forearmed.
assert(&bar != nullptr); // Let’s be totally sure.
...
}
• To express optionality
• Some objects/classes mostly appear as pointers in the sources
• Arrays, C-strings, pointer arithmetics
• Explicit delete
• To express that the object is placed on the heap
• Pointers are mutable (unlike references)
• Pointers are small and fast to copy (unlike some objects)
• Because of C
Why *ptr ?
17
const auto* const formatPtr = encodingFormatter.format;
Expects(formatPtr != nullptr);
const auto& format = *formatPtr;
delete &format; // looks strange
18
base::AtExitManager exit_manager;
base::AtExitManager::RegisterCallback(&FinalizeShaderTranslator, NULL);
Chromium, Google
https://chromium.googlesource.com/chromium
static AtExitManager* g_top_manager = NULL;
AtExitManager::AtExitManager() : next_manager_(g_top_manager) {
...
g_top_manager = this;
}
// destructor calls the registered callbacks
// and sets g_top_manager to next_manager_
19
{
actor_system_config cfg;
actor_system system{cfg};
...
}
CAF: C++ Actor Framework
https://github.com/actor-framework/actor-framework
20
class CWebBrowserOverlayWindow : public CWnd
{
private:
DECLARE_DYNAMIC(CWebBrowserOverlayWindow)
protected:
DECLARE_MESSAGE_MAP()
private:
CWnd* _pWebBrowserWindow;
CString _strWindowClassName;
COLORREF _transparentKeyColor;
public:
CWebBrowserOverlayWindow() :
_pWebBrowserWindow(),
_strWindowClassName(),
_transparentKeyColor(RGB(238, 96, 235))
{ }
virtual ~CWebBrowserOverlayWindow();
BOOL Create(HWND webBrowserWindowHandle);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnPaint();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};
21
class RegistryChangeWatcher :
private boost::noncopyable
{
private:
CRegKey _key;
bool _watchSubtree;
DWORD _notifications;
bool _useInvocationQueue;
HANDLE _event;
boost::thread _thread;
public:
typedef boost::signals2::signal<void ()> ChangeOccurredEvent;
ChangeOccurredEvent ChangeOccurred;
public:
RegistryChangeWatcher(HKEY keyParent, const std::wstring& keyName, bool watchSubtree,
RegistryChangeNotifications notifications, bool useInvocationQueue);
RegistryChangeWatcher(HKEY key, bool watchSubtree, RegistryChangeNotifications notifications,
bool useInvocationQueue);
~RegistryChangeWatcher();
private:
void Release();
static DWORD GetNotifyFilter(RegistryChangeNotifications notifications);
void PerformWatch();
void NotifyChange();
void RaiseChangeOccurred();
};
22
void Application::LaunchWebBrowserSync(const std::wstring& url)
{
ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_MAXIMIZE);
}
void Application::LaunchWebBrowserAsync(const std::wstring& url)
{
boost::thread(
boost::bind(&Application::LaunchWebBrowserSync, url));
}
23
auto launchWebBrowser(std::string_view url)
{
return std::async([](const std::string url) {
#ifdef _WIN32
return ShellExecuteA(nullptr, "open", url.c_str(),
nullptr, nullptr, SW_MAXIMIZE);
#endif
std::stringstream ss;
ss << "python -c "import webbrowser; webbrowser.open('" << url << "')"";
return std::system(ss.str().c_str());
#endif
}, std::string{url});
}
24
class CBatteryCheck : public CActive
{
public:
static CBatteryCheck* NewL(MBatteryObserver& aObserver);
static CBatteryCheck* NewLC(MBatteryObserver& aObserver);
~CBatteryCheck();
private:
CBatteryCheck(MBatteryObserver& aObserver);
void ConstructL(void);
void GetBatteryInfo();
void RunL();
void DoCancel();
private:
MBatteryObserver& iObserver;
CTelephony* iTelephony;
CTelephony::TBatteryInfoV1 iBatteryInfoV1;
CTelephony::TBatteryInfoV1Pckg iBatteryInfoV1Pckg;
TBool iGettingBattery;
};
An examplar Symbian class
https://github.com/DrJukka/Symbian_Codes
25
CBatteryCheck* CBatteryCheck::NewL(MBatteryObserver& aObserver) {
CBatteryCheck* self = CBatteryCheck::NewLC(aObserver);
CleanupStack::Pop(self);
return self;
}
CBatteryCheck* CBatteryCheck::NewLC(MBatteryObserver& aObserver) {
CBatteryCheck* self = new (ELeave) CBatteryCheck(aObserver);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CBatteryCheck::CBatteryCheck(MBatteryObserver& aObserver)
: CActive(EPriorityStandard), iObserver(aObserver), iBatteryInfoV1Pckg(iBatteryInfoV1)
{
CActiveScheduler::Add(this);
}
void CBatteryCheck::ConstructL(void)
{
iTelephony = CTelephony::NewL();
GetBatteryInfo();
}
26
class BatteryCheck
{
BatteryObserver& _observer;
Telephony _telephony;
bool _gettingBattery;
const BatteryInfo _batteryInfo;
public:
BatteryCheck(BatteryObserver& observer) :
_observer{observer},
_batteryInfo{},
_gettingBattery{IsGettingBattery(_batteryInfo)}
{}
private:
static bool IsGettingBattery(const BatteryInfo& batteryInfo) {
return ...;
}
};
Yikes!
27
28
codegen::StaticCompiler::StaticCompiler()
: m_precompiled_header_valid(false)
, m_debuginfo_enabled((std::getenv("NGRAPH_COMPILER_DEBUGINFO_ENABLE") != nullptr))
, m_enable_diag_output((std::getenv("NGRAPH_COMPILER_DIAG_ENABLE") != nullptr))
, m_source_name("code.cpp")
{
initialize();
}
void codegen::StaticCompiler::initialize()
{
...
}
Intel® nGraph™
https://github.com/NervanaSystems/ngraph
29
class BattleTank
{
Turret& _turret;
public:
BattleTank(Turret& turret) noexcept :
_turret{turret} {}
};
class BattleTank
{
gsl::not_null<Turret*> _turret;
public:
BattleTank(gsl::not_null<Turret*> turret) noexcept :
_turret{turret} {}
};
30
class ArmoredVehicle
{
Turret* _turret;
public:
explicit ArmoredVehicle(Turret* turret = nullptr) noexcept :
_turret{turret} {}
void MountTurret(Turret* turret) noexcept {
_turret = turret;
}
};
31
{
Turret mk44;
ArmouredVehicle rosomak{&mk44};
…
}
{
auto guns = std::vector<Turret>{};
auto cars = std::vector<ArmouredVehicle>{
ArmouredVehicle{&guns.emplace_back()}
};
}
32
class ArmoredVehicle
{
Turret* _turret = nullptr;
public:
explicit ArmoredVehicle() = default;
explicit ArmoredVehicle(Turret* turret) noexcept :
_turret{turret} {}
ArmoredVehicle(const ArmoredVehicle&) = delete;
ArmoredVehicle(ArmoredVehicle&& av) noexcept :
_turret{std::exchange(av._turret, nullptr)} {}
~ArmoredVehicle() noexcept {
delete _turret;
}
void MountTurret(Turret* turret) noexcept {
delete _turret;
_turret = turret;
}
};
It prevents:
ArmoredVehicle avs[] = { {} };
33
class ArmoredVehicle
{
std::unique_ptr<Turret> _turret;
public:
ArmoredVehicle() = default;
explicit ArmoredVehicle(std::unique_ptr<Turret> turret) noexcept :
_turret{std::move(turret)} {}
void MountTurret(std::unique_ptr<Turret> turret) noexcept {
_turret = std::move(turret);
}
};
34
struct noisy {
noisy() noexcept { std::cout << "def-ctor" << std::endl; }
noisy(const noisy&) = delete;
noisy(noisy&&) noexcept { std::cout << "move-ctor" << std::endl; }
};
void passByValue(noisy n) {
noisy n2{std::move(n)};
...
}
void passByRValRef(noisy&& n) {
noisy n2{std::move(n)};
...
}
passByValue(noisy{});
def-ctor
move-ctor
noisy n;
passByValue(std::move(n));
def-ctor
move-ctor
move-ctor
passByRValRef(noisy{});
def-ctor
move-ctor
noisy n;
passByRValRef(std::move(n));
def-ctor
move-ctor
35
class ngraph::codegen::Module
{
public:
Module(std::unique_ptr<llvm::Module> module);
~Module();
std::unique_ptr<llvm::Module> take_module();
private:
std::unique_ptr<llvm::Module> m_module;
};
Intel® nGraph™
https://github.com/NervanaSystems/ngraph
36
class ArmoredVehicle
{
std::optional<Turret> _turret;
public:
ArmoredVehicle() noexcept = default;
explicit ArmoredVehicle(Turret&& turret)
noexcept(std::is_nothrow_move_constructible_v<Turret>) :
_turret{std::move(turret)} {}
void MountTurret(Turret&& turret)
noexcept(std::is_nothrow_move_constructible_v<Turret>) {
_turret.emplace(std::move(turret));
}
};
37
Should I pass by value or reference?
= &vs
bbox3
Axis-Aligned Bounding Box
38
bbox1
bbox2
BBox merge(BBox bbox1, BBox bbox2) {
BBox bbox3;
for (size_t i = 0; i < Dim; ++i) {
bbox3.Min[i] = min(bbox1.Min[i], bbox2.Min[i]);
bbox3.Max[i] = max(bbox1.Max[i], bbox2.Max[i]);
}
return bbox3;
}
template<typename T, size_t Dim>
struct BBox {
Vec<T, Dim> Min, Max;
};
template<typename T, size_t Dim>
using Vec = std::array<T, Dim>;
LOOPED FORM
Can we unroll the loop at compile-time?
39
namespace {
template<typename T, size_t Dim, size_t... IX>
constexpr auto min(Vec<T, Dim> v1, Vec<T, Dim> v2, std::index_sequence<IX...>) noexcep
{
return Vec<T, Dim>{ std::min(v1[IX], v2[IX])... };
}
}
template<typename T, size_t Dim>
constexpr auto min(Vec<T, Dim> v1, Vec<T, Dim> v2) noexcept
{
return min(v1, v2, std::make_index_sequence<Dim>());
}
template<typename BBoxT>
constexpr auto merge(BBoxT bbox1, BBoxT bbox2) noexcept
{
return BBoxT{ min(bbox1.Min, bbox2.Min), max(bbox1.Max, bbox2.Max) };
}
FUNCTIONAL FORM
40
const auto bboxes = MakeRandomBoundingBoxes<int8_t, dim>(2 * 1024);
// Output by value
auto bbox = bboxes[0];
for (size_t i = 1; i < bboxes.size(); ++i) {
bbox = merge(bbox, bboxes[i]);
}
return bbox;
// Output by reference
auto bbox = bboxes[0];
for (size_t i = 1; i < bboxes.size(); ++i) {
merge(bbox, bboxes[i], bbox);
}
return bbox;
=
&
= =
& =
= &
& &
= =
& =
= &
& &
= =
& =
= &
& &
41
msvc
2017
15.5.7
gcc
libstdc++
7.1.0
clang
libc++
5.0.1
12 11
15 13
12 10
.45 .45
Dim = 1
T = int8_t
2048 b’boxes
In Out
2 4
µsec
8 16
.9 .9
.9 .9
.9 .9
.9 .9
2.2 1.8
1.7 1.7
2.3 2.4
0.5 0.5
15 30
17 33
15 28
4.8 20
1.2 1.2
1.2 1.2
1.2 1.2
1.2 1.2
7 7
4.2 4.2
5.7 5.6
2 2
24 35
22 38
19 33
9.3 25
2.1 2.1
2.1 2.1
2.1 2.1
2.1 2.1
13 13
9 10
11 11
5.5 5.5
39 48
32 49
33 44
19 34
4.8 4.8
4.8 4.8
4.8 4.8
4.5 4.5
24 27
18 23
25 25
17 17
45 81
45 43
43 79
37 46
15 14
15 14
15 14
15 14
49 53
48 43
3 25
34 3
88 74
87 73
86 79
89 77
67 55
7.5 40
8.1 55
6.3 41
11 16
9 10
10 15
5 9
32
182 157
160 141
176 163
166 144
132 34
12 232
15 112
10 244
21 38
13 19
18 33
9 14
64
42
template<typename Collection>
void TurboSort(Collection& collection) {
using namespace std;
while (next_permutation(begin(collection), end(collection))) {}
}
int main()
{
int fav_ints[] { 11, 8, 5, 3 };
std::list<std::string> fav_strings { "c++", "wombat", "batman" };
TurboSort(fav_ints);
TurboSort(fav_strings);
}
43
size(items);
items.size();
size_op{}(items);
struct size_op { auto operator()(…)( return …; ) };
CollectionHelper::GetSize(items);
44
class Complex {
float real_, imag_;
public:
float GetReal() const;
void SetReal(float real);
float& AtReal();
const float& AtReal() const;
...
};
struct complex {
float re, im;
};
45
auto c = std::complex<float>{1.f, 0.f};
c.real(2.f);
assert(std::real(c) == c.real());
struct complex { float re, im; };
complex c = {1.f};
c = {2.f};
46
class BattleTank {
public:
void FireCannon() { ... }
friend void FireCannon(BattleTank&);
};
void FireCannon(BattleTank& tank)
{
tank.FireCannon();
}
47
Passkey Idiom
class Document {
class MakerToken {
MakerToken() {} // It cannot be = default
friend class DocumentReader;
};
class UserToken {
UserToken() {}
friend class DocumentWriter;
};
int _data;
public:
Document(MakerToken) {}
void SetData(int data, MakerToken) { _data = data; }
int GetData(UserToken) { return _data; }
};
class DocumentReader {
public:
std::unique_ptr<Document> Read() {
auto doc = std::unique_ptr<Document>{new Document{{}}};
doc->SetData(42, {});
return doc;
}
};
class DocumentWriter {
public:
void Write(Document& doc) { doc.GetData({}); }
};
auto docReader = DocumentReader{};
auto docWriter = DocumentWriter{};
docWriter.Write(*docReader.Read());
Java: constructors vs static factory methods
48
Color(float, float, float);
Color(float, float, float, float);
Color(int);
Color(int, boolean);
Color(int, int, int);
Color(int, int, int, int);
Color.makeFromRGB(String);
Color.makeFromPalette(int, int, int);
Color.makeFromHex(int);
interface Color {}
class HexColor implements Color {
HexColor(int);
}
class RGBColor implements Color {
RGBColor(int, int, int);
}
class Boolean {
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
}
class Vehicle
{
public static Vehicle fromWheels(int wheelCount) {
if (wheelCount == 2) return new Bike();
else if (wheelCount == 4) return new Car();
else if (wheelCount == 6) return new Truck();
...
}
}
49
struct color {
uint32_t value;
color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {...}
static color from_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {...}
};
color make_rgba_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {...}
std::unique_ptr<std::mutex> make_mutex();
std::thread make_thread();
50
namespace boost { namespace gil {
template <typename ColorSpace, typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> >
struct layout {
typedef ColorSpace color_space_t;
typedef ChannelMapping channel_mapping_t;
};
struct red_t {};
struct green_t {};
struct blue_t {};
typedef mpl::vector3<red_t,green_t,blue_t> rgb_t;
typedef layout<rgb_t> rgb_layout_t;
typedef layout<rgb_t, mpl::vector3_c<int,2,1,0> > bgr_layout_t;
template <typename ColorBase, int K> struct kth_semantic_element_reference_type {
BOOST_STATIC_CONSTANT(int, semantic_index =
(mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value));
typedef typename kth_element_reference_type<ColorBase,semantic_index>::type type;
static type get(ColorBase& cb) { return at_c<semantic_index>(cb); }
};
template <typename ColorBase, typename Color>
struct color_element_reference_type :
public kth_semantic_element_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
template <typename ColorBase, typename Color>
typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) {
return color_element_reference_type<ColorBase,Color>::get(cb);
}
}}
51
btDiscreteDynamicsWorld* m_dynamicsWorld =
new btDiscreteDynamicsWorld(...);
...
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, ...);
btRigidBody* body = new btRigidBody(rbInfo);
body->setFriction(.5);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
Bullet Physics
https://github.com/bulletphysics/bullet3
namespace physics {
using RigidBodyRealmHook = boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
class RigidBody : public RigidBodyRealmHook
{
Realm& _realm;
public:
RigidBody(Realm& realm, bool makePresent = false) : _realm{realm} {
Present(makePresent);
}
bool Present() const { return is_linked(); }
void Present(bool present) {
if (present) {
if (!Present())
_realm._rigidBodies.push_back(*this);
}
else
unlink();
}
void Update() { /*...*/ }
};
class Realm {
using RigidBodyList = boost::intrusive::list<RigidBody,
boost::intrusive::constant_time_size<false>>;
RigidBodyList _rigidBodies;
public:
void UpdateAll() {
for (auto body : _rigidBodies)
body.Update();
}
friend class RigidBody;
};
} 52
auto realm = physics::Realm{};
auto ball = physics::RigidBody{realm};
ball.Present(true);
realm.UpdateAll();
ball.Present(false);
53
namespace physics {
struct RigidBodyData { bool present; };
class Realm {
plf::colony<RigidBodyData> _rigidBodies;
public:
void UpdateAll() {
for (auto& data : _rigidBodies) {
if (!data.present) continue;
/*...*/
}
}
friend class RigidBody;
};
class RigidBody {
Realm& _realm;
plf::colony<RigidBodyData>::iterator _data;
public:
RigidBody(Realm& realm, bool makePresent = true) :
_realm{realm},
_data{_realm._rigidBodies.insert(RigidBodyData{makePresent})} {}
~RigidBody() {
_realm._rigidBodies.erase(_data);
}
bool Present() const { return _data->present; }
void Present(bool present) { _data->present = true; }
};
}
Let’s play a game of…
54
55
Collection c;
loop {
int x = random(1...N);
c.find(x);
if (found)
c.remove(x);
else
c.add(x);
}
56
2 5 6 8 10
Approach 1:
x is an index in a collection of N slots
Approach 2:
x is a value of an element in a collection
2 5 6 8 10
• Sequencial
• Vector
• List
• Associative
• Tree
• Hash table
57
template<int Slots, typename RandomGenerator>
GameResult PlayFindAddRemove_bitset(int turns, RandomGenerator randomGenerator)
{
auto collection = std::bitset<Slots>();
auto sumOfSizes = int64_t{0};
auto size = int64_t{0};
for (int turn = 0; turn < turns; ++turn)
{
auto& item = collection[randomGenerator()];
size += item ? -1 : 1;
item = item ^ 1;
sumOfSizes += size;
}
return {sumOfSizes};
}
random() 26.57
int64[64] 29.19
int8[8] (bitset) 30.22
bitset<64> 36.68
vector<bool> (resize(N)) 37.45
google::dense_hash_set<int16> 46.91
tsl::hopscotch_set<int8> 52.93
vector<int16> 53.72
vector<uint8> (sorted) 64.13
boost::container::flat_set<uint16> 64.63
stx::btree_set<uint8> 65.38
btree::btree_set<int8> 76.04
deque<uint8> 81.22
deque<int8> (sorted) 137.1
unordered_set<uint8> 203.5
list<int64> 215.7
set<uint8> 244.6
list<uint32> (sorted) 272.8
google::sparse_hash_set<int8> 439.7
64 slots
58
random() 27.97
uint16[4096] 28.27
int8[512] (bitset) 30.28
bitset<4096> 36.27
vector<bool> (resize(N)) 36.80
google::dense_hash_set<uint16> 49.63
tsl::hopscotch_set<uint16> 66.32
btree::btree_set<uint64> 94.87
stx::btree_set<uint16> 115.2
boost::container::flat_set<int16> 153.2
vector<uint16> (sorted) 154.4
unordered_set<int16> 223.4
google::sparse_hash_set<int16> 252.4
set<uint32> 296.1
vector<int16> 913.9
deque<int32> (sorted) 1180
deque<int64> 1779
list<int16> 5819
list<int16> (sorted) 10577
4096 slots
POSITIONAL
59
using Array = std::array<int, 8>;
const Array orig_data = { 4, 213, 465, 5436, 523, 234, 643, 7 };
// Benchmark: Ordinary Function
{
Array data = orig_data;
TurboSort(data);
do_not_optimize(data);
}
auto randomEngine = std::mt19937{};
// Benchmark: std::function
{
std::function<void(Array&)> sortFunc = [](Array&) { throw 0; };
if (randomEngine() != 0) sortFunc = &TurboSort<Array>;
Array data = orig_data;
sortFunc(data);
do_not_optimize(data);
}
60
Ordinary Function std::function<>
233 µs 188 µs
94 µs 101 µs
89 µs 77 µs
msvc
2017
15.5.7
gcc
libstdc++
7.1.0
clang
libc++
5.0.1
61
UpdateRequestContract Business Domain
Primitives
Algorithms & Data StructuresCollisionBoxQuadTree
OptionalPriceRange
Variadic templates and auto-lambdas to the rescue. (≥ C++14)
How to iterate over a set of values in compile-time?
62
template<typename IntT, typename Func, IntT... IS>
void foreach_constexpr(std::integer_sequence<IntT, IS...>,
Func func)
{
const IntT zeroes[] {
(func(std::integral_constant<IntT, IS>{}), 0)...
};
}
foreach_constexpr(std::make_integer_sequence<int, 4>{}, [](auto ic) {
constexpr auto i = ic();
...
});
Twoja opinia na temat mojej prelekcji jest dla mnie bardzo ważna.
1. Wejdź w mój wykład znajdujący się w agendzie w aplikacji Eventory.
2. Oceń moją prelekcję i dodaj swój komentarz.
Dzięki temu będę wiedział, co Ci się podobało a co
powinienem ulepszyć!
65
https://github.com/Isameru
isameru@gmail.com
isameru
66
67

Weitere ähnliche Inhalte

Was ist angesagt?

C++ amp on linux
C++ amp on linuxC++ amp on linux
C++ amp on linuxMiller Lee
 
Writing native bindings to node.js in C++
Writing native bindings to node.js in C++Writing native bindings to node.js in C++
Writing native bindings to node.js in C++nsm.nikhil
 
Samsung WebCL Prototype API
Samsung WebCL Prototype APISamsung WebCL Prototype API
Samsung WebCL Prototype APIRyo Jin
 
Javascript compilation execution
Javascript compilation executionJavascript compilation execution
Javascript compilation executionFanis Prodromou
 
PyCon KR 2019 sprint - RustPython by example
PyCon KR 2019 sprint  - RustPython by examplePyCon KR 2019 sprint  - RustPython by example
PyCon KR 2019 sprint - RustPython by exampleYunWon Jeong
 
Node.js flow control
Node.js flow controlNode.js flow control
Node.js flow controlSimon Su
 
Hibernate Import.Sql I18n
Hibernate Import.Sql I18nHibernate Import.Sql I18n
Hibernate Import.Sql I18nyifi2009
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumlercorehard_by
 
Refactoring for testability c++
Refactoring for testability c++Refactoring for testability c++
Refactoring for testability c++Dimitrios Platis
 
Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2drewz lin
 
Ghost Vulnerability CVE-2015-0235
Ghost Vulnerability CVE-2015-0235Ghost Vulnerability CVE-2015-0235
Ghost Vulnerability CVE-2015-0235Rajivarnan (Rajiv)
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesAndrey Karpov
 
How Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerHow Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerAndrey Karpov
 
Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Mr. Vengineer
 

Was ist angesagt? (20)

C++ amp on linux
C++ amp on linuxC++ amp on linux
C++ amp on linux
 
Pledge in OpenBSD
Pledge in OpenBSDPledge in OpenBSD
Pledge in OpenBSD
 
Writing native bindings to node.js in C++
Writing native bindings to node.js in C++Writing native bindings to node.js in C++
Writing native bindings to node.js in C++
 
Samsung WebCL Prototype API
Samsung WebCL Prototype APISamsung WebCL Prototype API
Samsung WebCL Prototype API
 
Javascript compilation execution
Javascript compilation executionJavascript compilation execution
Javascript compilation execution
 
Vulkan 1.1 Reference Guide
Vulkan 1.1 Reference GuideVulkan 1.1 Reference Guide
Vulkan 1.1 Reference Guide
 
PyCon KR 2019 sprint - RustPython by example
PyCon KR 2019 sprint  - RustPython by examplePyCon KR 2019 sprint  - RustPython by example
PyCon KR 2019 sprint - RustPython by example
 
Node.js flow control
Node.js flow controlNode.js flow control
Node.js flow control
 
Hibernate Import.Sql I18n
Hibernate Import.Sql I18nHibernate Import.Sql I18n
Hibernate Import.Sql I18n
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
 
Refactoring for testability c++
Refactoring for testability c++Refactoring for testability c++
Refactoring for testability c++
 
Node day 2014
Node day 2014Node day 2014
Node day 2014
 
Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2Easily mockingdependenciesinc++ 2
Easily mockingdependenciesinc++ 2
 
NS2 Shadow Object Construction
NS2 Shadow Object ConstructionNS2 Shadow Object Construction
NS2 Shadow Object Construction
 
Ghost Vulnerability CVE-2015-0235
Ghost Vulnerability CVE-2015-0235Ghost Vulnerability CVE-2015-0235
Ghost Vulnerability CVE-2015-0235
 
Tiramisu概要
Tiramisu概要Tiramisu概要
Tiramisu概要
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
 
How Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerHow Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzer
 
Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。
 
OpenGL SC 2.0 Quick Reference
OpenGL SC 2.0 Quick ReferenceOpenGL SC 2.0 Quick Reference
OpenGL SC 2.0 Quick Reference
 

Ähnlich wie 4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)

Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsAzul Systems, Inc.
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?Doug Hawkins
 
How to Write Node.js Module
How to Write Node.js ModuleHow to Write Node.js Module
How to Write Node.js ModuleFred Chien
 
Protocol handler in Gecko
Protocol handler in GeckoProtocol handler in Gecko
Protocol handler in GeckoChih-Hsuan Kuo
 
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17LogeekNightUkraine
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptSeok-joon Yun
 
Cross Platform App Development with C++
Cross Platform App Development with C++Cross Platform App Development with C++
Cross Platform App Development with C++Joan Puig Sanz
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheeltcurdt
 
如何透過 Go-kit 快速搭建微服務架構應用程式實戰
如何透過 Go-kit 快速搭建微服務架構應用程式實戰如何透過 Go-kit 快速搭建微服務架構應用程式實戰
如何透過 Go-kit 快速搭建微服務架構應用程式實戰KAI CHU CHUNG
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneDroidConTLV
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleThierry Wasylczenko
 
The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196Mahmoud Samir Fayed
 
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxbradburgess22840
 
单元测试必知必会
单元测试必知必会单元测试必知必会
单元测试必知必会智杰 付
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoinknight1128
 

Ähnlich wie 4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński) (20)

Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Marat-Slides
Marat-SlidesMarat-Slides
Marat-Slides
 
3
33
3
 
How to Write Node.js Module
How to Write Node.js ModuleHow to Write Node.js Module
How to Write Node.js Module
 
Protocol handler in Gecko
Protocol handler in GeckoProtocol handler in Gecko
Protocol handler in Gecko
 
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScript
 
Ac2
Ac2Ac2
Ac2
 
Cross Platform App Development with C++
Cross Platform App Development with C++Cross Platform App Development with C++
Cross Platform App Development with C++
 
Apache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheelApache Commons - Don\'t re-invent the wheel
Apache Commons - Don\'t re-invent the wheel
 
V8
V8V8
V8
 
如何透過 Go-kit 快速搭建微服務架構應用程式實戰
如何透過 Go-kit 快速搭建微服務架構應用程式實戰如何透過 Go-kit 快速搭建微服務架構應用程式實戰
如何透過 Go-kit 快速搭建微服務架構應用程式實戰
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
 
Java Concurrency
Java ConcurrencyJava Concurrency
Java Concurrency
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196The Ring programming language version 1.7 book - Part 87 of 196
The Ring programming language version 1.7 book - Part 87 of 196
 
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
 
单元测试必知必会
单元测试必知必会单元测试必知必会
单元测试必知必会
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 

Kürzlich hochgeladen

Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 

Kürzlich hochgeladen (20)

Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 

4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)

  • 1. Evolution of C++ Class Design Mariusz Łapiński
  • 2. 2
  • 3. 3 More Effective C++ 35 New Ways to Improve Your Programs and Designs 1995
  • 4. 4 Framework Design Guidelines Conventions, Idioms, and Patterns for Reusable .NET Libraries 2008
  • 5. 5 class VPtrBase { private: bool destructible; unsigned int nref; bool share; protected: VPtrBase (); VPtrBase (const VPtrBase& pb); virtual ~VPtrBase () = 0; public: virtual VPtrBase* clone () const = 0; VPtrBase* incRef (CloningBehaviourT cb = CB_ALLOW); bool decRef (); bool isDestructable () const; bool isReferred () const; bool isShared () const; bool canShare () const; void forbidDestruction (); void allowDestruction (); void forbidSharing (); void allowSharing (); void assign (const VPtrBase& pb); };
  • 6. 6 class CObject { public: virtual CRuntimeClass* GetRuntimeClass() const; virtual ~CObject(); void* operator new(size_t nSize) throw(...); ... BOOL IsSerializable() const; BOOL IsKindOf(const CRuntimeClass* pClass) const; virtual void Serialize(CArchive& ar); virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; ... }; Microsoft Foundation Classes
  • 7. 7
  • 8. 8 • The QObject class is the base class of all Qt objects. • You can connect a signal to a slot with connect() and destroy the connection with disconnect(). To avoid never ending notification loops you can temporarily block signals with blockSignals(). The protected functions connectNotify() and disconnectNotify() make it possible to track connections. • QObjects organize themselves in object trees. When you create a QObject with another object as parent, the object will automatically add itself to the parent's children() list. • Every object has an objectName() and its class name can be found via the corresponding metaObject(). • Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties. You also need to run the Meta Object Compiler on the source file. • Some QObject functions, e.g. children(), return a QObjectList. QObjectList is a typedef for QList<QObject *>.
  • 10. 10 // We need to call this to set up global state for TensorFlow. tensorflow::port::InitMain(argv[0], &argc, &argv); TensorFlow, Google https://github.com/tensorflow/tensorflow void InitMain(const char* usage, int* argc, char*** argv) {}
  • 11. 11 // Initialization int mpiInitError = MPI_Init(argc, argv); ... // Cleanup MPI_Finalize(); MPI
  • 12. 12 // Initialization HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ... // Cleanup CoUninitialize(); COM
  • 13. 13 // Initialization GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); ... // Cleanup GdiplusShutdown(gdiplusToken); GDI+
  • 14. 14 BOOL WINAPI GetMessage( _Out_ LPMSG lpMsg, _In_opt_ HWND hWnd, _In_ UINT wMsgFilterMin, _In_ UINT wMsgFilterMax ); WinAPI
  • 15. 15 // Initialization v8::V8::InitializeICUDefaultLocation(argv[0]); v8::V8::InitializeExternalStartupData(argv[0]); std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform(); v8::V8::InitializePlatform(platform.get()); v8::V8::Initialize(); ... // Cleanup v8::V8::Dispose(); v8::V8::ShutdownPlatform(); V8, Google https://github.com/v8/v8
  • 16. 16 PassRegistry *Registry = PassRegistry::getPassRegistry(); initializeCore(*Registry); initializeCodeGen(*Registry); ... LLVM https://github.com/llvm-mirror/llvm void foo(Bar& bar) { assert(&bar != nullptr); // Forewarned is forearmed. assert(&bar != nullptr); // Let’s be totally sure. ... }
  • 17. • To express optionality • Some objects/classes mostly appear as pointers in the sources • Arrays, C-strings, pointer arithmetics • Explicit delete • To express that the object is placed on the heap • Pointers are mutable (unlike references) • Pointers are small and fast to copy (unlike some objects) • Because of C Why *ptr ? 17 const auto* const formatPtr = encodingFormatter.format; Expects(formatPtr != nullptr); const auto& format = *formatPtr; delete &format; // looks strange
  • 18. 18 base::AtExitManager exit_manager; base::AtExitManager::RegisterCallback(&FinalizeShaderTranslator, NULL); Chromium, Google https://chromium.googlesource.com/chromium static AtExitManager* g_top_manager = NULL; AtExitManager::AtExitManager() : next_manager_(g_top_manager) { ... g_top_manager = this; } // destructor calls the registered callbacks // and sets g_top_manager to next_manager_
  • 19. 19 { actor_system_config cfg; actor_system system{cfg}; ... } CAF: C++ Actor Framework https://github.com/actor-framework/actor-framework
  • 20. 20 class CWebBrowserOverlayWindow : public CWnd { private: DECLARE_DYNAMIC(CWebBrowserOverlayWindow) protected: DECLARE_MESSAGE_MAP() private: CWnd* _pWebBrowserWindow; CString _strWindowClassName; COLORREF _transparentKeyColor; public: CWebBrowserOverlayWindow() : _pWebBrowserWindow(), _strWindowClassName(), _transparentKeyColor(RGB(238, 96, 235)) { } virtual ~CWebBrowserOverlayWindow(); BOOL Create(HWND webBrowserWindowHandle); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnPaint(); afx_msg BOOL OnEraseBkgnd(CDC* pDC); };
  • 21. 21 class RegistryChangeWatcher : private boost::noncopyable { private: CRegKey _key; bool _watchSubtree; DWORD _notifications; bool _useInvocationQueue; HANDLE _event; boost::thread _thread; public: typedef boost::signals2::signal<void ()> ChangeOccurredEvent; ChangeOccurredEvent ChangeOccurred; public: RegistryChangeWatcher(HKEY keyParent, const std::wstring& keyName, bool watchSubtree, RegistryChangeNotifications notifications, bool useInvocationQueue); RegistryChangeWatcher(HKEY key, bool watchSubtree, RegistryChangeNotifications notifications, bool useInvocationQueue); ~RegistryChangeWatcher(); private: void Release(); static DWORD GetNotifyFilter(RegistryChangeNotifications notifications); void PerformWatch(); void NotifyChange(); void RaiseChangeOccurred(); };
  • 22. 22 void Application::LaunchWebBrowserSync(const std::wstring& url) { ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_MAXIMIZE); } void Application::LaunchWebBrowserAsync(const std::wstring& url) { boost::thread( boost::bind(&Application::LaunchWebBrowserSync, url)); }
  • 23. 23 auto launchWebBrowser(std::string_view url) { return std::async([](const std::string url) { #ifdef _WIN32 return ShellExecuteA(nullptr, "open", url.c_str(), nullptr, nullptr, SW_MAXIMIZE); #endif std::stringstream ss; ss << "python -c "import webbrowser; webbrowser.open('" << url << "')""; return std::system(ss.str().c_str()); #endif }, std::string{url}); }
  • 24. 24 class CBatteryCheck : public CActive { public: static CBatteryCheck* NewL(MBatteryObserver& aObserver); static CBatteryCheck* NewLC(MBatteryObserver& aObserver); ~CBatteryCheck(); private: CBatteryCheck(MBatteryObserver& aObserver); void ConstructL(void); void GetBatteryInfo(); void RunL(); void DoCancel(); private: MBatteryObserver& iObserver; CTelephony* iTelephony; CTelephony::TBatteryInfoV1 iBatteryInfoV1; CTelephony::TBatteryInfoV1Pckg iBatteryInfoV1Pckg; TBool iGettingBattery; }; An examplar Symbian class https://github.com/DrJukka/Symbian_Codes
  • 25. 25 CBatteryCheck* CBatteryCheck::NewL(MBatteryObserver& aObserver) { CBatteryCheck* self = CBatteryCheck::NewLC(aObserver); CleanupStack::Pop(self); return self; } CBatteryCheck* CBatteryCheck::NewLC(MBatteryObserver& aObserver) { CBatteryCheck* self = new (ELeave) CBatteryCheck(aObserver); CleanupStack::PushL(self); self->ConstructL(); return self; } CBatteryCheck::CBatteryCheck(MBatteryObserver& aObserver) : CActive(EPriorityStandard), iObserver(aObserver), iBatteryInfoV1Pckg(iBatteryInfoV1) { CActiveScheduler::Add(this); } void CBatteryCheck::ConstructL(void) { iTelephony = CTelephony::NewL(); GetBatteryInfo(); }
  • 26. 26 class BatteryCheck { BatteryObserver& _observer; Telephony _telephony; bool _gettingBattery; const BatteryInfo _batteryInfo; public: BatteryCheck(BatteryObserver& observer) : _observer{observer}, _batteryInfo{}, _gettingBattery{IsGettingBattery(_batteryInfo)} {} private: static bool IsGettingBattery(const BatteryInfo& batteryInfo) { return ...; } }; Yikes!
  • 27. 27
  • 28. 28 codegen::StaticCompiler::StaticCompiler() : m_precompiled_header_valid(false) , m_debuginfo_enabled((std::getenv("NGRAPH_COMPILER_DEBUGINFO_ENABLE") != nullptr)) , m_enable_diag_output((std::getenv("NGRAPH_COMPILER_DIAG_ENABLE") != nullptr)) , m_source_name("code.cpp") { initialize(); } void codegen::StaticCompiler::initialize() { ... } Intel® nGraph™ https://github.com/NervanaSystems/ngraph
  • 29. 29 class BattleTank { Turret& _turret; public: BattleTank(Turret& turret) noexcept : _turret{turret} {} }; class BattleTank { gsl::not_null<Turret*> _turret; public: BattleTank(gsl::not_null<Turret*> turret) noexcept : _turret{turret} {} };
  • 30. 30 class ArmoredVehicle { Turret* _turret; public: explicit ArmoredVehicle(Turret* turret = nullptr) noexcept : _turret{turret} {} void MountTurret(Turret* turret) noexcept { _turret = turret; } };
  • 31. 31 { Turret mk44; ArmouredVehicle rosomak{&mk44}; … } { auto guns = std::vector<Turret>{}; auto cars = std::vector<ArmouredVehicle>{ ArmouredVehicle{&guns.emplace_back()} }; }
  • 32. 32 class ArmoredVehicle { Turret* _turret = nullptr; public: explicit ArmoredVehicle() = default; explicit ArmoredVehicle(Turret* turret) noexcept : _turret{turret} {} ArmoredVehicle(const ArmoredVehicle&) = delete; ArmoredVehicle(ArmoredVehicle&& av) noexcept : _turret{std::exchange(av._turret, nullptr)} {} ~ArmoredVehicle() noexcept { delete _turret; } void MountTurret(Turret* turret) noexcept { delete _turret; _turret = turret; } }; It prevents: ArmoredVehicle avs[] = { {} };
  • 33. 33 class ArmoredVehicle { std::unique_ptr<Turret> _turret; public: ArmoredVehicle() = default; explicit ArmoredVehicle(std::unique_ptr<Turret> turret) noexcept : _turret{std::move(turret)} {} void MountTurret(std::unique_ptr<Turret> turret) noexcept { _turret = std::move(turret); } };
  • 34. 34 struct noisy { noisy() noexcept { std::cout << "def-ctor" << std::endl; } noisy(const noisy&) = delete; noisy(noisy&&) noexcept { std::cout << "move-ctor" << std::endl; } }; void passByValue(noisy n) { noisy n2{std::move(n)}; ... } void passByRValRef(noisy&& n) { noisy n2{std::move(n)}; ... } passByValue(noisy{}); def-ctor move-ctor noisy n; passByValue(std::move(n)); def-ctor move-ctor move-ctor passByRValRef(noisy{}); def-ctor move-ctor noisy n; passByRValRef(std::move(n)); def-ctor move-ctor
  • 35. 35 class ngraph::codegen::Module { public: Module(std::unique_ptr<llvm::Module> module); ~Module(); std::unique_ptr<llvm::Module> take_module(); private: std::unique_ptr<llvm::Module> m_module; }; Intel® nGraph™ https://github.com/NervanaSystems/ngraph
  • 36. 36 class ArmoredVehicle { std::optional<Turret> _turret; public: ArmoredVehicle() noexcept = default; explicit ArmoredVehicle(Turret&& turret) noexcept(std::is_nothrow_move_constructible_v<Turret>) : _turret{std::move(turret)} {} void MountTurret(Turret&& turret) noexcept(std::is_nothrow_move_constructible_v<Turret>) { _turret.emplace(std::move(turret)); } };
  • 37. 37 Should I pass by value or reference? = &vs
  • 38. bbox3 Axis-Aligned Bounding Box 38 bbox1 bbox2 BBox merge(BBox bbox1, BBox bbox2) { BBox bbox3; for (size_t i = 0; i < Dim; ++i) { bbox3.Min[i] = min(bbox1.Min[i], bbox2.Min[i]); bbox3.Max[i] = max(bbox1.Max[i], bbox2.Max[i]); } return bbox3; } template<typename T, size_t Dim> struct BBox { Vec<T, Dim> Min, Max; }; template<typename T, size_t Dim> using Vec = std::array<T, Dim>; LOOPED FORM
  • 39. Can we unroll the loop at compile-time? 39 namespace { template<typename T, size_t Dim, size_t... IX> constexpr auto min(Vec<T, Dim> v1, Vec<T, Dim> v2, std::index_sequence<IX...>) noexcep { return Vec<T, Dim>{ std::min(v1[IX], v2[IX])... }; } } template<typename T, size_t Dim> constexpr auto min(Vec<T, Dim> v1, Vec<T, Dim> v2) noexcept { return min(v1, v2, std::make_index_sequence<Dim>()); } template<typename BBoxT> constexpr auto merge(BBoxT bbox1, BBoxT bbox2) noexcept { return BBoxT{ min(bbox1.Min, bbox2.Min), max(bbox1.Max, bbox2.Max) }; } FUNCTIONAL FORM
  • 40. 40 const auto bboxes = MakeRandomBoundingBoxes<int8_t, dim>(2 * 1024); // Output by value auto bbox = bboxes[0]; for (size_t i = 1; i < bboxes.size(); ++i) { bbox = merge(bbox, bboxes[i]); } return bbox; // Output by reference auto bbox = bboxes[0]; for (size_t i = 1; i < bboxes.size(); ++i) { merge(bbox, bboxes[i], bbox); } return bbox; = &
  • 41. = = & = = & & & = = & = = & & & = = & = = & & & 41 msvc 2017 15.5.7 gcc libstdc++ 7.1.0 clang libc++ 5.0.1 12 11 15 13 12 10 .45 .45 Dim = 1 T = int8_t 2048 b’boxes In Out 2 4 µsec 8 16 .9 .9 .9 .9 .9 .9 .9 .9 2.2 1.8 1.7 1.7 2.3 2.4 0.5 0.5 15 30 17 33 15 28 4.8 20 1.2 1.2 1.2 1.2 1.2 1.2 1.2 1.2 7 7 4.2 4.2 5.7 5.6 2 2 24 35 22 38 19 33 9.3 25 2.1 2.1 2.1 2.1 2.1 2.1 2.1 2.1 13 13 9 10 11 11 5.5 5.5 39 48 32 49 33 44 19 34 4.8 4.8 4.8 4.8 4.8 4.8 4.5 4.5 24 27 18 23 25 25 17 17 45 81 45 43 43 79 37 46 15 14 15 14 15 14 15 14 49 53 48 43 3 25 34 3 88 74 87 73 86 79 89 77 67 55 7.5 40 8.1 55 6.3 41 11 16 9 10 10 15 5 9 32 182 157 160 141 176 163 166 144 132 34 12 232 15 112 10 244 21 38 13 19 18 33 9 14 64
  • 42. 42 template<typename Collection> void TurboSort(Collection& collection) { using namespace std; while (next_permutation(begin(collection), end(collection))) {} } int main() { int fav_ints[] { 11, 8, 5, 3 }; std::list<std::string> fav_strings { "c++", "wombat", "batman" }; TurboSort(fav_ints); TurboSort(fav_strings); }
  • 43. 43 size(items); items.size(); size_op{}(items); struct size_op { auto operator()(…)( return …; ) }; CollectionHelper::GetSize(items);
  • 44. 44 class Complex { float real_, imag_; public: float GetReal() const; void SetReal(float real); float& AtReal(); const float& AtReal() const; ... }; struct complex { float re, im; };
  • 45. 45 auto c = std::complex<float>{1.f, 0.f}; c.real(2.f); assert(std::real(c) == c.real()); struct complex { float re, im; }; complex c = {1.f}; c = {2.f};
  • 46. 46 class BattleTank { public: void FireCannon() { ... } friend void FireCannon(BattleTank&); }; void FireCannon(BattleTank& tank) { tank.FireCannon(); }
  • 47. 47 Passkey Idiom class Document { class MakerToken { MakerToken() {} // It cannot be = default friend class DocumentReader; }; class UserToken { UserToken() {} friend class DocumentWriter; }; int _data; public: Document(MakerToken) {} void SetData(int data, MakerToken) { _data = data; } int GetData(UserToken) { return _data; } }; class DocumentReader { public: std::unique_ptr<Document> Read() { auto doc = std::unique_ptr<Document>{new Document{{}}}; doc->SetData(42, {}); return doc; } }; class DocumentWriter { public: void Write(Document& doc) { doc.GetData({}); } }; auto docReader = DocumentReader{}; auto docWriter = DocumentWriter{}; docWriter.Write(*docReader.Read());
  • 48. Java: constructors vs static factory methods 48 Color(float, float, float); Color(float, float, float, float); Color(int); Color(int, boolean); Color(int, int, int); Color(int, int, int, int); Color.makeFromRGB(String); Color.makeFromPalette(int, int, int); Color.makeFromHex(int); interface Color {} class HexColor implements Color { HexColor(int); } class RGBColor implements Color { RGBColor(int, int, int); } class Boolean { public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } } class Vehicle { public static Vehicle fromWheels(int wheelCount) { if (wheelCount == 2) return new Bike(); else if (wheelCount == 4) return new Car(); else if (wheelCount == 6) return new Truck(); ... } }
  • 49. 49 struct color { uint32_t value; color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {...} static color from_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {...} }; color make_rgba_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {...} std::unique_ptr<std::mutex> make_mutex(); std::thread make_thread();
  • 50. 50 namespace boost { namespace gil { template <typename ColorSpace, typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> > struct layout { typedef ColorSpace color_space_t; typedef ChannelMapping channel_mapping_t; }; struct red_t {}; struct green_t {}; struct blue_t {}; typedef mpl::vector3<red_t,green_t,blue_t> rgb_t; typedef layout<rgb_t> rgb_layout_t; typedef layout<rgb_t, mpl::vector3_c<int,2,1,0> > bgr_layout_t; template <typename ColorBase, int K> struct kth_semantic_element_reference_type { BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value)); typedef typename kth_element_reference_type<ColorBase,semantic_index>::type type; static type get(ColorBase& cb) { return at_c<semantic_index>(cb); } }; template <typename ColorBase, typename Color> struct color_element_reference_type : public kth_semantic_element_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {}; template <typename ColorBase, typename Color> typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) { return color_element_reference_type<ColorBase,Color>::get(cb); } }}
  • 51. 51 btDiscreteDynamicsWorld* m_dynamicsWorld = new btDiscreteDynamicsWorld(...); ... btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, ...); btRigidBody* body = new btRigidBody(rbInfo); body->setFriction(.5); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); Bullet Physics https://github.com/bulletphysics/bullet3
  • 52. namespace physics { using RigidBodyRealmHook = boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>; class RigidBody : public RigidBodyRealmHook { Realm& _realm; public: RigidBody(Realm& realm, bool makePresent = false) : _realm{realm} { Present(makePresent); } bool Present() const { return is_linked(); } void Present(bool present) { if (present) { if (!Present()) _realm._rigidBodies.push_back(*this); } else unlink(); } void Update() { /*...*/ } }; class Realm { using RigidBodyList = boost::intrusive::list<RigidBody, boost::intrusive::constant_time_size<false>>; RigidBodyList _rigidBodies; public: void UpdateAll() { for (auto body : _rigidBodies) body.Update(); } friend class RigidBody; }; } 52 auto realm = physics::Realm{}; auto ball = physics::RigidBody{realm}; ball.Present(true); realm.UpdateAll(); ball.Present(false);
  • 53. 53 namespace physics { struct RigidBodyData { bool present; }; class Realm { plf::colony<RigidBodyData> _rigidBodies; public: void UpdateAll() { for (auto& data : _rigidBodies) { if (!data.present) continue; /*...*/ } } friend class RigidBody; }; class RigidBody { Realm& _realm; plf::colony<RigidBodyData>::iterator _data; public: RigidBody(Realm& realm, bool makePresent = true) : _realm{realm}, _data{_realm._rigidBodies.insert(RigidBodyData{makePresent})} {} ~RigidBody() { _realm._rigidBodies.erase(_data); } bool Present() const { return _data->present; } void Present(bool present) { _data->present = true; } }; }
  • 54. Let’s play a game of… 54
  • 55. 55 Collection c; loop { int x = random(1...N); c.find(x); if (found) c.remove(x); else c.add(x); }
  • 56. 56 2 5 6 8 10 Approach 1: x is an index in a collection of N slots Approach 2: x is a value of an element in a collection 2 5 6 8 10 • Sequencial • Vector • List • Associative • Tree • Hash table
  • 57. 57 template<int Slots, typename RandomGenerator> GameResult PlayFindAddRemove_bitset(int turns, RandomGenerator randomGenerator) { auto collection = std::bitset<Slots>(); auto sumOfSizes = int64_t{0}; auto size = int64_t{0}; for (int turn = 0; turn < turns; ++turn) { auto& item = collection[randomGenerator()]; size += item ? -1 : 1; item = item ^ 1; sumOfSizes += size; } return {sumOfSizes}; }
  • 58. random() 26.57 int64[64] 29.19 int8[8] (bitset) 30.22 bitset<64> 36.68 vector<bool> (resize(N)) 37.45 google::dense_hash_set<int16> 46.91 tsl::hopscotch_set<int8> 52.93 vector<int16> 53.72 vector<uint8> (sorted) 64.13 boost::container::flat_set<uint16> 64.63 stx::btree_set<uint8> 65.38 btree::btree_set<int8> 76.04 deque<uint8> 81.22 deque<int8> (sorted) 137.1 unordered_set<uint8> 203.5 list<int64> 215.7 set<uint8> 244.6 list<uint32> (sorted) 272.8 google::sparse_hash_set<int8> 439.7 64 slots 58 random() 27.97 uint16[4096] 28.27 int8[512] (bitset) 30.28 bitset<4096> 36.27 vector<bool> (resize(N)) 36.80 google::dense_hash_set<uint16> 49.63 tsl::hopscotch_set<uint16> 66.32 btree::btree_set<uint64> 94.87 stx::btree_set<uint16> 115.2 boost::container::flat_set<int16> 153.2 vector<uint16> (sorted) 154.4 unordered_set<int16> 223.4 google::sparse_hash_set<int16> 252.4 set<uint32> 296.1 vector<int16> 913.9 deque<int32> (sorted) 1180 deque<int64> 1779 list<int16> 5819 list<int16> (sorted) 10577 4096 slots POSITIONAL
  • 59. 59 using Array = std::array<int, 8>; const Array orig_data = { 4, 213, 465, 5436, 523, 234, 643, 7 }; // Benchmark: Ordinary Function { Array data = orig_data; TurboSort(data); do_not_optimize(data); } auto randomEngine = std::mt19937{}; // Benchmark: std::function { std::function<void(Array&)> sortFunc = [](Array&) { throw 0; }; if (randomEngine() != 0) sortFunc = &TurboSort<Array>; Array data = orig_data; sortFunc(data); do_not_optimize(data); }
  • 60. 60 Ordinary Function std::function<> 233 µs 188 µs 94 µs 101 µs 89 µs 77 µs msvc 2017 15.5.7 gcc libstdc++ 7.1.0 clang libc++ 5.0.1
  • 61. 61 UpdateRequestContract Business Domain Primitives Algorithms & Data StructuresCollisionBoxQuadTree OptionalPriceRange
  • 62. Variadic templates and auto-lambdas to the rescue. (≥ C++14) How to iterate over a set of values in compile-time? 62 template<typename IntT, typename Func, IntT... IS> void foreach_constexpr(std::integer_sequence<IntT, IS...>, Func func) { const IntT zeroes[] { (func(std::integral_constant<IntT, IS>{}), 0)... }; } foreach_constexpr(std::make_integer_sequence<int, 4>{}, [](auto ic) { constexpr auto i = ic(); ... });
  • 63.
  • 64. Twoja opinia na temat mojej prelekcji jest dla mnie bardzo ważna. 1. Wejdź w mój wykład znajdujący się w agendzie w aplikacji Eventory. 2. Oceń moją prelekcję i dodaj swój komentarz. Dzięki temu będę wiedział, co Ci się podobało a co powinienem ulepszyć!
  • 66. 66
  • 67. 67