What C++ Can Do For Embedded Systems
Dan Saks - EOC - Duration: 04:05:21

You'll find Workshop setup instructions, project files, and slides in the download link located under "Files Provided by the Speaker(s)" on the left (you need to be logged in to access those files).
Prerequisite: Solid knowledge of C. Some exposure to C++ and classes will be helpful, but not essential.
C is a “low-level high-level” language. It has flow control and data structures found in many other high-level languages. It also has “low-level” data types and operators that let you get close to the hardware. The result is a language that’s easier to use than assembly language, but with comparable performance. As such, C has been a natural choice for many embedded applications, including automotive, aerospace, consumer products, and medicine. So why consider using C++ instead of C?
Embedded software keeps showing up in more and more products. More powerful processors and larger memories have led to ever more complex systems, with increasing demands for safety and security. Embedded developers need more effective tools to help reduce, if not eliminate, defects that pose safety and security risks.
C++ is nearly all of C, plus a whole lot more. C++ classes, namespaces, and templates help manage large-scale software. C++’s richer and more rigorous type system can turn potential run-time defects into code that simply doesn’t compile or link. This leads to software that’s easier to use correctly and harder to use incorrectly.
This workshop uses concrete embedded programming examples to show in detail how selected C++ language features can benefit embedded software development. The selected features include:
- references
- overloaded functions and operators
- enhancements for enumerations
- classes, member functions, and access control
- user-defined conversions
Attendees will have the opportunity to do programming exercises during the workshop. You'll be able to compile the exercises using desktop tools such as GNU C++ or Visual C++. We've provided a sample program that you can use to test your compiler setup before you attend.
How to control the sequence of different object initialization (constructor running) if the object is defined as globe type?
If you want to ensure that the program initializes certain objects in a particular order, you have some options. Here are a couple...
C++ guarantees that objects at namespace scope (which includes global scope) in a single translation unit will be initialized in the order that the objects are defined from top to bottom and left to right. For example, given these definitions at global scope in a single source file:
gadget g1 {37}, g2 {42};
widget w;
the program will initialize g1, g2, and then w in that order.
If you can't gather all the global objects into a single translation unit, then you can write a function that uses a sequence of "placement new" expressions to initialize the objects in the desired order. For example,
gadget g1 = new (x) gadget {37};
gadget g2 = new (y) gadget {42};
widget *w = new (z) widget;
will initialize g1, g2, and then w in that order. x, y, and z have to be pointer expressions whose values refer to uninitialized static storage that can hold the gadget and widget objects.
Thanks
I am not sure, but maybe you can find the answer to your question in the "Effective C++" book by Scott Meyers in "item 4: Make sure that objects are initialized before they're used". This is a book I got recommended some time ago, and that I would recommend it to anybody willing to program in C++. You can articles talking about this item in the internet. I do not copy any link here, because I am not sure about copyright infrigement.
Thanks Dan for a compelling practical presentation on how C++ can help embedded developers.
I would like to cast a glance over the most recent C++ standards (post C++17), with this in mind, I was wondering if you had any insights on what the most relevant additions may be for embedded development.
12:25:33 From Phil Kasiecki : I wasn't even aware that there was a more recent dialect of C than C99, though I was aware there was a lot less change there than C++ 12:25:54 From Jay Cosper : FYI there are two different ZIP files. The one on the abstract is different 12:26:14 From Jacob Beningo To Josh C(privately) : The abstract zip is what you need to set up the environment for the course that uses the second zip file 12:26:37 From Prasanna : Can someone provide way to download for zoom web clients? 12:28:20 From CPannell : can you repost the link? Chat history starts when you join, so I missed it 12:28:29 From Jacob Beningo : Yes, it is being recorded 12:29:04 From CPannell : ❤️ 12:29:38 From Prasanna : Thanks Jacob. 12:29:56 From Gillian Minnehan : Oh I see. We need the zip that is being posted right now in addition to the zip that was sent over email a few days ago. 12:31:29 From Prasanna : Yes they are different 12:31:37 From Enrico : there was an email sent a few days ago ? so 3 zip packages ? link in chat, website, and email ? or is email and website the same ? 12:31:48 From Jacob Beningo : Yes Gillian. The first zip was to help you get set up for the course. The one we’re posting now is the course materials 12:32:14 From Stephane : email and website the same 12:32:18 From Jacob Beningo : The one in the abstract is different. The ones posted here / on dropbox / or emailed are the same 12:32:40 From Enrico : thanks 12:33:27 From Jean Apolo : Compiler optimization can affect how it treats R-values and L-values. 12:34:27 From Michael Kirkhart : Successfully received and uncompressed ZIP file. Thanks. 12:36:57 From Michael Kirkhart : Finally, someone has given a reasonable explanation (with examples) of lvalues and rvalues. This alone was worth the price of admission. Thanks! 12:39:45 From Phil Kasiecki : If you're interviewing for at least a senior-level embedded software position, you're virtually guaranteed to be asked about volatile. 12:39:56 From Jean Apolo : The explanation of L-Values and R-Values and their quirks is absolute perfection! :D 12:42:48 From Stephane : https://www.youtube.com/watch?v=NZtr93iL3R0 12:43:15 From Jean Apolo : Even Junior embedded software position interviews ask about volatile and const keywords and their use. ESPECIALLY if the position is for low-level C/C++ driver development. 12:44:08 From Michael Kirkhart : Yes, and there is a very good reason for the need for the volatile keyword when doing driver development. 12:45:34 From Enrico : Had to to volatile on a microchip compiler because the a for loop delay that was being optimized out even with -O0. It pops up regardless of complexity of code lol 12:47:04 From Enrico : spelling/grammar mistakes galore...sorry 12:47:21 From Tobías Lifschitz : I recommend this page to check and understand declarations https://cdecl.org/ 12:47:33 From Enrico : 100p. Great website. 12:47:42 From Enrico : I think theres even a vs code pluggin 12:49:00 From Phil Kasiecki : Ah yes - I once worked with someone on a C++ standards committee, and in code reviews he was a big stickler for the use of magic numbers. 12:50:11 From Gillian Minnehan : I feel like I comment on the removal of magic numbers on nearly every merge request / pull request code review I'm added to 12:51:18 From Phil Kasiecki : One of the first things I learned in C++ is to use const instead of #define for constants. I had no idea for years that const was in C as well because it was simply not taught anywhere I learned C. 12:51:58 From Jay Cosper : what about const vs constexpr 12:52:01 From Jay Cosper : oh 12:52:11 From Phil Kasiecki : Right on cue Jay! 12:57:01 From Jean Apolo : That and good TDD techniques in the cycle can really save time during the dreaded "crunch time". 12:58:09 From Michael Kirkhart : Yes, this is something I used to tell other developers: provide a development environment to turn run-time errors into compile time errors. 12:58:17 From Enrico To Jacob Beningo(privately) : how long is this workshop ? 12:58:39 From Jacob Beningo To Enrico(privately) : It is 4 hours 12:58:47 From Jacob Beningo To Enrico(privately) : 3 - 4 hours :-) 12:58:48 From Jean Apolo : With a good OS like Linux or other open-source automation tools you can really automate the TDD process. 12:59:04 From magarac : If I use C++ framework but write C-style , would those C++ features still help with catching bugs at compile time ? 13:01:19 From Jean Apolo : For catching compiler bugs, MOST definitely! Dan Saks will go over this. 13:01:33 From Jean Apolo : *For catching bugs in compile time 13:01:55 From Michael Kirkhart : Or you can use the typedef keyword to make the enumeration an actual type (just like you can do with structures). 13:02:20 From Leandro Pérez : In C I use typedef to use in the same way 13:02:25 From Leandro Pérez : exactly 13:03:37 From Gillian Minnehan : I like the trick of making the last enum called "count" which gives you the number of enums 13:03:58 From Michael Kirkhart : Yes, I have used that technique as well. 13:04:04 From Jean Apolo : Same here. 13:05:14 From Michael Kirkhart : Oh, man - I did not know this. This could cause problems. 13:05:44 From Jean Apolo : Now we know, and knowing is half the battle. 13:06:08 From Michael Kirkhart : Score 1 for C++ 13:06:47 From Phil Kasiecki : They never did tell us what the other half is, though. 13:06:59 From Michael Kirkhart : Provided you pay attention to the warnings 13:07:15 From Phil Kasiecki : (Probably one of those "the rest is left as an exercise for the reader" deals.) 13:07:15 From Charles Miller : Except the count isn't semantically a item in the enum collection, Gillian. I use a separate constexpr uint32_t xenum_count = … Requires more work/care, but won't let me use "count" as an enum-thing. 13:07:18 From Jean Apolo : IF your compiler is nice enough to give you warnings. 13:08:22 From Raul Pando : If only there was a built-in method to get the "size" of an enum 13:09:08 From Gillian Minnehan : @Charles Fair point. However, I don't like to have expressions that have to be maintained though. It would be easy to forget to increment the count if you added an enum. Is there a way to statically check that count is the correct value? 13:09:11 From Jean Apolo : (Sigh) Man I wish I can attend the full lecture but I have to get back to work soon :( 13:09:59 From Jacob Beningo : Jean, we are recording it. We should have the recording up this evening for you to then parse through at your convenience. 13:10:09 From Jim Kresse : @Jean, same here. The agenda didn't show that it was 4 hours long. 13:10:11 From Jean Apolo : If any of you guys have your company allot time for you to attend your workshop consider yourselves blessed. 13:10:24 From Enrico To Jacob Beningo(privately) : im just skipping work :p 13:10:33 From Jay Cosper : no native Linux? 13:10:34 From Enrico To Jacob Beningo(privately) : sorry meant to share with everyone 13:10:35 From Jacob Beningo To Enrico(privately) : Lol that’s the way to do it 13:10:37 From Michael Kirkhart : Well, I actually took vacation days for this conference. 13:10:48 From Enrico : im just skipping work :p 13:10:55 From Michael Kirkhart : Not that is stopping work from intruding :( 13:11:11 From Jean Apolo : @Jim Damn, Four hours?! I'm gunna miss all of the fun :( 13:11:17 From Jacob Beningo : By the way, that is good feedback. I did not realize we didn’t post that it was a half day workshop 13:11:37 From Nathan O. : For anyone using Linux environment : you should be able to replace "cmd /c del" with "rm" for the clean commands in all makefiles 13:11:42 From Vladimir Kurylovich : It work in WSL 13:12:21 From Josh C : It says on the workshop site that the duration is 4hr, but the calendar invite download was only 40mins 13:12:33 From Jean Apolo : Hopefully the entire workshop is recorded. I'll try the exercises this weekend. 13:12:41 From Cole Wyant : those two makefiles work on my mac. they should work on linux too 13:12:45 From Jacob Beningo : Hmm interesting. Thanks for letting us know! 13:13:59 From Jean Apolo : Thanks for pointing that out Dan. 13:14:06 From Michael Kirkhart : Yes, it builds in my linux VM 13:14:14 From Jean Apolo : A little grep and awk'n will fix that issue 13:14:49 From Jim Kresse : I've already gone 20 minutes over what the calendar invite showed. I'm unfortunately going to have to drop off. :-( 13:14:49 From Jean Apolo : Anyway I got to go :( 13:15:18 From Enrico To Jacob Beningo(privately) : Is the chat being recorded too ? 13:15:21 From Cole Wyant : Those who can't see files in the chat can replace their linker flags variable with this LFLAGS = -g -o $@ -Wl,-map,$*$(MAP) 13:15:30 From Erin RobotGrrl : Looking forward to trying this workshop fully when the recording is posted! 13:15:44 From Jacob Beningo To Enrico(privately) : Yes the chat is recorded too 13:15:51 From Enrico To Jacob Beningo(privately) : thanks! 13:16:35 From Mathieu P : Works with Cygwin compilers (meaning pass on gcc and failed on g++) 13:17:32 From Jean Apolo : Excellent Workshop as always Dan Saks, keep spreading the good news of Embedded C++ and maybe, just maybe, we get embedded C++ to mainstream use. It makes it so much easier to integrate the code to Embedded Linux Applications. 13:20:44 From Gabe Ferencz : For anyone else hopping between the C and C++ compilers, the -B flag is your friend. My C++ compiler was happy with the C compiled binary. 13:20:51 From Prasanna : On Mac, I see this error. ld: unknown option: -Map=everyday.m clang: error: linker command failed with exit code 1 (use -v to see invocation) 13:21:27 From Michael Kirkhart : Was able to run this example - compiles for C, does not compile for C++ 13:23:06 From Prasanna : neccccvbtienuengnnbidgvhjlvvldcjjdbjlkkdlne 13:23:50 From Phil Kasiecki : I saw the same thing, Michael - I didn't try gcc until you mentioned it (used g++), but I saw what you saw. 13:24:26 From Charles Miller : Gillian, static_assert(MyEnum::LAST_ENUM + 1== xenum_count); 13:24:52 From Charles Miller : (forgot error string, but you get it) 13:25:30 From Charles Miller : (only legal if xenum_count is a constexpr) 13:26:54 From Gillian Minnehan : @Charles Makes sense, but this only works if LAST_ENUM stays the last enum (I'm guessing its not actually called LAST_ENUM) 13:27:53 From Charles Miller : Yep. That's why my code is still littered with N_ENUMS as the last enum :-) 13:35:06 From Enrico : C is chill. My kind of dude 13:35:22 From Nathan O. : @Charles @Gillian doesn't that defeat the purpose of an enum containing all 'valid' values that the variable can take ? In C in make sense, its all integer in the end. In C++ I guess it makes less sense. Especially once we get overloaded operators on enum (how do you increment LAST_ENUM?) 13:36:59 From Charles Miller : @Nathan, I think Dan is about to show us ;-) 13:37:05 From Gillian Minnehan : @Nathan I agree, it seems less logical for C++ 13:40:18 From Michael Kirkhart : This is where the concept of a reference variable comes in? (day &x) 13:40:34 From Phil Kasiecki : I think that's what's coming right up, Michael... 13:41:36 From Keith Hill : I get an endless loop when I solve it simply 13:44:06 From Cameron Kluza : Interesting, was operator overloading one of the original motivations for C++ adding references? 13:46:34 From Leandro Pérez : What important is understand to use pass by value or pass by reference to mantain the RAM usange low 13:46:42 From Leandro Pérez : *usage 13:46:50 From Michael Foreman : This is great. This is answering a lot of questions that made me nervous to move from C to C++ 13:47:52 From Dave Comer : Stay tuned. Wait until you hear about object creation and memory segmentation….I’m hoping Dan has a good lecture on this for mission critical systems. 13:49:36 From ABDUL : 16 got warning The enum type 'day' is unscoped. Prefer 'enum class' over 'enum. 13:51:53 From Gillian Minnehan : I at first tried to use d += 1 and it told me that the += operator wasn't defined haha ? 13:52:18 From Hatim Jamali : because the return should be int 13:52:21 From Hatim Jamali : I think 13:53:05 From Gillian Minnehan : Yeah it gave me: error: no match for 'operator+=' (operand types are 'day' and 'int') 13:53:12 From Cole Wyant : Does this exercise imply that we can assign non-listed values to our enum type during runtime? 13:53:23 From Michael Kirkhart : Got 1st part working - now dealing with the compile error in the #if 0 section. 13:53:49 From Cole Wyant : I tried to be smart with the value for Saturday and gave myself an infinite loop. 13:54:01 From Raul Pando : :) 13:54:02 From Keith Hill : I got the same infinite loop. 13:54:21 From Keith Hill : But doing a modulus function seems most appropriate, mathematically. 13:54:32 From Nathan O. : Is there a ++operator that acts differently than operator++ ? 13:54:32 From Michael Kirkhart : Got 2nd part working 13:57:25 From Nathan O. : I have seen C programmers preferring to use ++i in their loops too, on the argument of speed also ;) 13:59:52 From Michael Kirkhart : For those programmers making that claim, have them compile to assembly for both ++i and i++ and see if there is a difference in the generated instructions. 14:00:11 From Gillian Minnehan : ^smart 14:00:36 From Felipe Prado : day 14:00:36 From CPannell : day 14:00:43 From CPannell : auto? 14:00:43 From Erwin : refernce 14:00:43 From Aditya S : auto :) 14:00:44 From Puru Patil : & 14:00:45 From ABDUL : &day 14:00:51 From Charles Miller : Ref to day 14:00:56 From Alexandre Cursi Gil Bodi : day & 14:01:21 From Michael Kirkhart : Anyone can speculate and argue about something indefinitely, but evidence will answer the question and stop the speculation. 14:01:24 From CPannell : oh yeah, day & 14:02:22 From Nathan O. : @Michael sure I agree, although proving something is always true can be difficult ;) 14:02:48 From Michael Kirkhart : Yes, that is true. 14:02:54 From Tim Michals : also, std::move support 14:04:07 From Charles Miller : Compiler Explorer is your friend! 14:04:28 From Puru Patil : isn't it a good idea to add something as end_range or start_range for any enum? 14:05:57 From Puru Patil : enum day { DayNone=-1, Sunday=0, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Noday }; 14:06:04 From Puru Patil : is this ok!? or valid? 14:06:55 From CPannell : couldn't you just do a modulo on the increment so it wraps? I mean that doesn't save you from other arithmetic mistakes 14:07:07 From Nathan O. : So we can't increment a variable that's set to Saturday if you want to know the next day after Saturday ? 14:07:34 From Gillian Minnehan : @CPannell wouldn't we get an infinite loop then? 14:07:42 From CPannell : like time itself 14:07:59 From Nathan O. : day d = Saturday; d++; It makes sense in term of logic. 14:08:18 From Puru Patil : for -- operator we will need one more at the start of enum list 14:08:24 From Charles Miller : MAX_UINT16 + 1 = 0 14:08:24 From Keith Hill : that's what I thought all along; modulo arithmetic is "standard" for weekdays! 14:08:27 From Nathan O. : Unles you are in Europe in which case Sunday is right after Saturday and the week start on Monday ;) 14:11:31 From Michael Kirkhart : Yes, but you can handle that in the manner of your choice in the overload function. 14:12:10 From Nathan O. : @Michael except you can't because in this case we get the infinite loop in our for loop 14:12:39 From Michael Kirkhart : Yes, but you can choose not to do any adjustments. 14:13:13 From CPannell : not a fan of inline inlines? 14:14:51 From Charles Miller : @Dan, can you put the body of an inline func in the .cpp file? (Will the compiler be smart enough to see it as an inline request?) 14:15:19 From Dave Comer : Doh! We’ve been dates ;) 14:15:26 From Dave Comer : dated 14:15:38 From Michael Kirkhart : Yes, I remember the register keyword (now I am revealing my age). 14:16:18 From Dave Comer : Let’s just say, post 1980’s ;) 14:16:23 From Erwin : isn't inlining what most Compilers for embedded systems like Keil and IAR should do if optimzing for Speed or size? 14:16:26 From Nathan O. : I think we still don't have inlining over several compilation units (if defined in a .cpp file) 14:17:36 From Dave Comer : #pragma once 14:17:56 From Michael Kirkhart : #pragma once does not fix this 14:18:04 From Dave Comer : Why? 14:18:33 From Dave Comer : (Not saying your wrong, just curious) 14:19:21 From Michael Kirkhart : You could have multiple .cpp source files which include your .h, and if the .h implements the function, each .cpp source will compile it as part of its compile output, and at link time, the linker will complain because each one of these .cpp objects has a copy of the function. 14:20:43 From Michael Kirkhart : https://www.ebay.com/itm/323794176416?chn=ps&norover=1&mkevt=1&mkrid=711-213727-13078-0&mkcid=2&itemid=323794176416&targetid=4580496732614413&device=c&mktype=&googleloc=&poi=&campaignid=418233788&mkgroupid=1230353745471221&rlsatarget=pla-4580496732614413&abcId=9300542&merchantid=51291&msclkid=ecacecfdc2d71411644d8e97180c3d43 14:20:55 From Michael Kirkhart : Kind of pricy? 14:21:11 From Michael Kirkhart : About $300 14:21:28 From Michael Kirkhart : Well, $289 to be exact 14:22:02 From Puru Patil : Memory mapped I/O then? 14:22:18 From Puru Patil : but actually mapping to memmory 14:30:33 From Michael Kirkhart : I am a big fan of the types provided in stdint.h 14:30:52 From Michael Kirkhart : If you want a 32 bit unsigned integer, you can get one using uint32_t 14:41:45 From Alexandre Cursi Gil Bodi : SEG_F shifts 16 bits SEG_G shifts 15 bits Is that correct? 14:42:11 From Alexandre Cursi Gil Bodi : Right. THank you 14:42:20 From Alexandre Cursi Gil Bodi : :) 14:42:26 From Michael Kirkhart : I am a hardware guy 14:42:39 From Michael Kirkhart : I am also a software guy, so if there is a problem, it is always my fault. 14:47:17 From Puru Patil : do you mean 05-01.2? 14:47:25 From Puru Patil : or 05-02s 14:55:24 From ABDUL : I see this print differently special_register *const IOPMOD = (special_register*)(as_bus_address)(SYSCFG + 0x5000); special_register* const IOPDATA = (special_register*)(as_bus_address)(SYSCFG + 0x5000); what is the difference can you please say? 14:56:00 From Nathan O. : IOPDATA should be at 0x5008 14:56:25 From ABDUL : Ok Thanks 14:58:44 From Josh C : another consequence of the workshop timing (40mins invite vs 4hr duration) is that apparently we can no longer join the Zoom meeting - tried switching to another device, but "This Live Session has Ended. A recording will be provided here soon." - guess I'll keep this one active, and be back in a few ? 15:03:29 From ABDUL : I used unsigned constexpr is that Ok to use this? 15:05:03 From Geoff : any benefit to adding "static" to these? 15:05:10 From ABDUL : Yes it complied on visual c++. 15:05:19 From Geoff : the ones above I was thinking 15:06:36 From ABDUL : I used here; unsigned constexpr SYSCFG = 0x03FF0000; 15:12:06 From Mark Tuma : This is a great explanation of volatile, thank you 15:17:37 From Michael Kirkhart : LOL! 15:17:50 From Nathan O. : Microsoft finds its own software is a virus ! 15:18:02 From Cole Wyant : On my gnu build, I had to make the loop counter in the delay loop volatile as well to get the proper visual effect. 15:19:18 From Michael Kirkhart : I remember going through the exercise of eliminating all warnings from our codebase along with turning the warning level all the way up. Our code could run on our target or on a Windows PC. With the warnings turned up all the way, we found Microsoft headers generated warnings. 15:19:45 From Erwin : the delay loop pretty good optimized :-) 15:21:38 From Felipe Prado : could you please explain the logic why the volatile keyword goes on the left of * instead of on the right? 15:21:56 From Felipe Prado : you mentioned the idea in the beginning, but it's not quite clear for me 15:23:10 From Felipe Prado : thanks 15:28:50 From Tim Kaiser : I get a compile error if I put the volatile to the reference main.cpp: In function ‘void seg7_init()’: seg7.h:5:17: error: passing ‘volatile simulator::special_register’ as ‘this’ argument discards qualifiers [-fpermissive] 5 | #define SEG_ALL 0x1FC00u // 'u' avoids signed-to-unsigned warnings | ^~~~~~~~ 15:29:04 From Tim Kaiser : Works fine without 15:29:39 From Tim Kaiser : OK, thanks 15:29:56 From schen : @Tom, I got that too. 15:39:04 From Charles Miller : Try using "enum class day" and find out what kind of casting h*ll you get into! 15:47:40 From Nathan O. : I'm getting some issue with seg7_put(middle) that's considered as a call to seg7_put(segment) (not cast to unsigned). I need to cast to unsigned in the main loop calls 15:49:21 From Nathan O. : Oh right, I got what happened, nevermind. 15:52:10 From Alexandre Cursi Gil Bodi : Java would mess that up :-) 15:52:45 From Cole Wyant : Does the order matter on the definitions of these overloads? 15:53:07 From Cole Wyant : I had weird behavior if I swapped the order. 15:53:15 From Jay Cosper : Doesn't seem to add to clarity tho 15:53:35 From Michael Kirkhart : No. What the compiler actually does is create a unique internal name for each function based on its name, return value, and arguments. 15:53:53 From Michael Kirkhart : Look up "C++ name mangling" online 15:54:55 From Mark Tuma : @Cole, add some definitions before the declarations: void seg7_put(int); void seg7_put(char); void seg7_put(glyph); 15:55:34 From Cole Wyant : ? thanks 15:55:50 From Mark Tuma : The compiler needs help to know what options it will have... 15:59:23 From Jay Cosper : that's really useful 16:00:21 From Charles Miller : Underlying types are a game changer for storing enums in, say, packed structs for config storage, instead of casting to uint8_t. Promotes size efficiency. 16:05:24 From Rob Gordon : I thought MISRA standard discouraged the use of range ids for enum lists such as begin/end. 16:13:39 From ABDUL : Can please also explain about this "friend class iopdata_effect_type;." it is also in example you privided? 16:16:46 From Mark Tuma : Great worskp, thanks Dan! 16:16:53 From Alexandre Cursi Gil Bodi : had a great time 16:16:55 From Gabriel Aguilar Lemus : Excellent workshop! 16:16:55 From Alexandre Cursi Gil Bodi : Thank you, Dan 16:16:57 From Gillian Minnehan : Amazing! Thank you 16:16:57 From Nathan O. : Thanks Dan ! 16:16:57 From Puru Patil : Thanks for great workshop 16:16:59 From Cameron Kluza : Thanks Dan! 16:17:01 From Mathieu P : Thx 16:17:03 From Gabriel Aguilar Lemus : Hope we can get the slides 16:17:03 From Anson C : Thank you 16:17:03 From Babis Sarantoglou : Amazing workshop! I learned a lot! 16:17:04 From Carlos : Excellent - wish you had another hour or so! 16:17:06 From Phil Kasiecki : Thank you, Dan! This was excellent. 16:17:06 From Josh C : We still mostly use C, but use CppUTest for unit testing, so dipping into more C++ for tests, and now mocks as well. ? 16:17:07 From Márton : Thank you so much! 16:17:08 From Jay Cosper : thanks for the intro and material!!! 16:17:08 From Alexandre Cursi Gil Bodi : Excellent teaching 16:17:08 From Erwin : thanks very much 16:17:08 From Brian Cabebe : Thanks. Very well done. 16:17:09 From ABDUL : Great workshop if you can please say little bit about friend 16:17:11 From schen : Thanks, Dan. 16:17:13 From Steve Wheeler : Good information. Thanks. 16:17:14 From Craig Ogawa : Thank you! 16:17:18 From Swetika : Thank You!! 16:17:19 From Hatim Jamali : Thanks 16:17:21 From Lisa Shi : Thanks 16:17:22 From Leroy Monitor : Much more than expected, Great job 16:17:24 From lynetta : Thank you very much! 16:17:31 From Thomas Schaertel : Thank you! Well done! 16:17:34 From Alexandre Cursi Gil Bodi : It's a way to violate the encapsulation :D 16:17:42 From Adrian : Thanks for the workshop! 16:17:53 From Mark Turner : Excellent presentation! 16:18:00 From Charles Miller : If I don't get my Dan Saks fix every couple of years, I get grump. Truly a wonderful session, Dan. Thank you! Hope to see you at CppCon. 16:18:03 From ABDUL : Thank you so much. 16:18:05 From Keith Hill : Great motivation for die-hard C programmers! 16:18:31 From Alexandre Cursi Gil Bodi : True that, Keith 16:18:38 From Michael Kirkhart : This was an excellent workshop! 16:18:50 From Aditya S : Thanks for the workshop Dan. Can we go for follow up question somewhere? 16:19:20 From Gillian Minnehan : https://embeddedonlineconference.com/workshop/What_Cplusplus_Can_Do_For_Embedded_Systems 16:20:50 From Alex : a greate talk 16:20:51 From Stephane : You can rate all the sessions from the schedule page 16:21:42 From Aditya S : Many thanks. 16:21:49 From Gabriel Aguilar Lemus : Thanks!
This has come super late, but thank you for this fantastic workshop!