CppCon 2015: Scott Schurr “constexpr: Introduction”

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Is it possible to overload on constexpr? For example I have two algorithms for computing the same output and one is slow but can be made constexpr (slow compilation but zero time during run time) the other is faster (big O style faster) but cannot be made constexpr. I want automagic overloading, I know I can write constexpr auto res = some_func<c_input>() or constexpr auto res = some_func_constexpr(c_input) vs const auto res = some_func_runtime(r_input), but I want to be able to write constexpr auto res = some_func(input) and const auto res = some_func(input) both invoking different algorithm based whether constexpr result was requested or not.

👍︎︎ 3 👤︎︎ u/MarekKnapek 📅︎︎ Oct 09 2015 🗫︎ replies

Looks like I picked the wrong week to quit thinking about chocolate

👍︎︎ 3 👤︎︎ u/craptacus 📅︎︎ Oct 09 2015 🗫︎ replies

An informative talk, but the format he used wasted a lot of time, which forced him to gloss over some points. Lots of time spent answering questions that were going to be answered in later slides, and then more time spent handing out chocolate.

I guess there's a reason most formats are set length speach + Q&A with any time remaining afterward.

👍︎︎ 3 👤︎︎ u/Rangsk 📅︎︎ Oct 11 2015 🗫︎ replies
Captions
so my name's Scott sure you can call me Scott everybody hi Scott alright so we want this to be I I don't know about we I want this to be an interactive kind of a session we're in the middle of the afternoon we've all gone you know our brains are kind of wrung out if you have a question or an assertion get my attention I may not notice your right away you can throw things at me that's alright so let's don't save your questions for the end let's let's get them out if we don't get through all the slides that's okay the most important ones are at the front so don't worry about slowing things down especially you folks who are hesitant to hold up your hands and say I have a question I particularly want to hear from you and I have a way to reinforce that so everyone who asks a question or who helps me out I'm from Portland Oregon I like things that are biodegradable so this is about as biodegradable as it gets this is chocolate I work for a place called ripple labs they're based in San Francisco and strangely enough Ghirardelli chocolate comes from San Francisco so if you if if you help the the presentation by asking a question or correcting me if I'm wrong I'm not an expert I'm way open to to people saying hey that's not quite right you you get a reward I've got 80 of these I don't think I'll run out but it's possible so ask ask early and ask often so so I want to talk about contacts per so with our there are two parts oh there's a question you get chocolate right away what does Oh what does the loan well so I need to to pass this chocolate back can you pass that chocolate back Thanks so the concrete company I there there a number of pictures in here and most of them relate to concrete or stone or something like that and that's because and we'll get will get more into this context fur is all about finding values or things at compile time at least that's my take on it that's that's what I find to be valuable about context for context per is not only a compile time thing and we'll again we'll get into those details later on but the thing that I think is cool about it is what it allows you to do a compile time without having to do template metaprogramming which I have tried and I occasionally succeeded but but this is way easier in my opinion so let's get started more concrete so context for what an odd word why would someone use this word I think partly it was something that they could introduce into the language that nobody else had used yet because there's this problem with key words that you don't want to put in a key word that somebody else has already used so yeah it's a really odd word but it's kind of this oddball contraction of constant expression so that's what we're gonna end up talking about is constant expressions Const exper allows you to evaluate expressions at compile time it's kind of like template metaprogramming but it uses a familiar C++ syntax so it's easier to maintain you don't have to be a freakin expert in order to figure this stuff out a lot of it reads like well depending on whether you're dealing with C++ 11 or C++ 14 it's pretty much standard C++ code which is something I think is is really nifty it only produces constant values so this is stuff that you know once it's produced it's done it's not moving it's not changing so like I said it can't change at runtime so why is that interesting who cares used but actually one of the motivations for this talk was I got excited about cost expert and I walk up to programmers like I always do in a bus station or whatever and say you know let me tell you about context per and they say well if you're doing all this stuff a compile time well what what's the good of that what's useful that you can do a compile time it turns out in my opinion there are a lot of things you can do a compile time that are pretty useful some of that is because of my background as an embedded developer I did about it embedded developing for quite a number of years and the more stuff you can do ahead the less you know the the errors are caught early the errors are caught a compile time just the very best possible time your footprint is smaller and probably I'm getting way ahead of my yeah all right so no you know run time cost there's when that value is already present in your image you're not computing it at runtime your compiler did that work for you you've reduced your executable footprint which most people don't care about but if you're doing embedded development or a constrained platform this can make a big difference and probably the most important part is whenever you can you know I'm and I'm not saying Const X first solves all problems Const X bar is a very specific kind of a thing you can't do everything at compile time for most problems that's fine I understand that but there are things that you can do a compile-time and if you can my position is that you should so the things that you can find a compile-time you're way ahead if you can find those errors if you can find you know whatever the problem is if you can find that at compile time you just made a big win because the compiler you know runtime errors you have to actually execute the code before the error happens the compiler walks all of your code every time you compile so even an error in an oddball little corner the compiler will find that so you've nailed that you don't have to rely on your unit tests getting into the odd corners you don't have synchronization concerns this is sort of a set up for my talk tomorrow which I hope some of you will attend but if you build containers at runtime and you happen to know what all of those values are going to be then there's often a synchronization problem as you build that container if it contains a vector or whatever if there's a race folks getting into that container then you have to do all the synchronization work you have to do your threads and locking and all that business and why bother with that if you don't need to so if you have a constant container make it a constant expert constant container and now you don't have any races dealing with that container and we'll talk more about that tomorrow so Const expert is a new keyword it was introduced in C++ 11 see if I can stop getting ahead of myself so the keyword is applied in two different cases one is when you're declaring a value or an object and in that case you say Const X / int or whatever and that says that it's going to be a literal type the other thing you can do is you can use that constant expert keyword for declaring functions and constructors so those are the two situations where the context per keyword is going to play into what you're up to and where you're going to want to drop that context for keyword in so the place we're going to spend most of our attention is on context / functions later on but probably the more important part is the context / values so we can make contexts for values it's easier if I look over here so here we've declared a number of these values now there's an interesting aspect to this slide every single one of those asserts is a static assert that means that every one of those checks is happening at compile time and if the compiler is not happy with the result it will stop you at compile time if there's a problem it will not get into production you won't even finish compiling you won't get an object file so even though we're going to be talking about context / code a lot it's the context for keyword on the value that's the most important part that's what's going to stop you yes yeah so the question is what's the difference between the contacts print and saying static constant and and at this point you know that's it's basically interchangeable as we get to something that's more complicated in an INT and you get some chocolate can you pass this back okay dude if I throw it I may hit you all right okay it's dangerous I hit somebody in the face with some skittles ones so yeah we're we're dealing with with an INT a static constant would work great as the object types get more interesting than like as a matter of fact if you get to a floating point type you can't do that and context for an float get along just great so yeah well so the reason I did double is because as we were talking about in earlier you can do static constant if you do a static haunts double that's not something that you can operate on a compile time so these are all you know the double in particular any of the floating point types the compiler will know about those and you can do static asserts on cons to expert doubles which you could not do it yeah just fun chocolate and I'm gonna have to develop my throwing arm if I start getting questions from the back so those are all data types that are at namespace scope you can also put stuff inside of a function that at PI in the function so that's worth thinking about if you have how many of you have heard the phrase magic statics yeah okay okay so it sits around so I'm not gonna spend a whole lot of time talking about this but the fact that that context per PI now you know that's a constant but but if that were being computed with a context per function when you walk into the function see the the compilers job is to make sure that that value is initialized before the function executes and that means it has as long as it gets initialized it can it doesn't matter so oftentimes there are if you have a function that has you know is used in a multi-threaded situation there have previously before C++ 11 or 14 or something like that there were race conditions where you could have a function where you to enter into the function the static variable hadn't been initialized yet it would start initializing somebody else would race in with and and now that's all being protected you know if you're using a modern compiler the compilers are effectively doing locks in order to prevent that from happening well if you do it with context / nobody needs a lock because the values determined at compile time it's all set to go yes yeah yeah so so the question was what's the advantage of contacts / versus static Const and and in this particular case because it's a it's a floating-point number we can initialize that very easily so it's it's no value yet let's wait until we compute a value and hey good catch yeah so the so the question is is is is there not let's see if I can well okay yeah but yeah so let's let's not let's not deal with with with a macro but I one of one of the things that will happen if if this were a more complicated expression than just dropping a floating-point value in there and here's your chocolate is that that flag to see whether something needs to be initialized a there's that race condition when you first enter secondly there is a very very small cost to entering the function every time you enter the function because it has to see whether that value was initialized or not so in the case of a context / value it knows that was initialized it was initialized at compile time so that test of the flag has now gone away so there's yeah so there is value yeah I didn't think his his question was about macros I thought his was about like static answer or whatever so yeah anyway so we great questions thank you very much appreciate that we need to get more in the back so I can develop my throwing arm so you can you can also declare static data members of literal types inside of a struct so those are basically or your options of where you can where you can use contacts book so yes in the struct the let's see will get there this is the question so inside of the struct that has to be static because it's going to be constant so it's true for all instances of that struct so you can't have a non-static member that's also Const expert okay and you get chocolate Oh iris more chocolate coming let's get to some of those questions later on okay but I I want to reinforce the questions I almost made it I'll make it gonna make you change chase that chocolate so so values can be any literal type that's including floating-point types character literals pointer literals objects and we'll get to how to declare an object so that a pretty much any type so that it can be taken as a literal they require no storage declaration so a lot of these things you have to if you if you had a static and the struct for example you have to declare the static in the struct and then you have to declare storage for at some place in the CPP file typically you don't have to do that with context where the compiler takes care of it for you and it's not okay to have context for parameters on a function don't ask me why I'm not part of the Standards Committee I'm sure they had great reasons but and if you try to do this the compiler will stop you so don't worry about it the compiler will let you know so how do you use these things you can use them anywhere a literals could be used so you can use them as template parameters non-type template parameters you can use them to determine the dimensions of an array you can use them for enumeration initialization and you can use them in standard run I'm code so the compiler really knows the value you know that's if you think about how templates get instantiated there's a bunch of thrashing about and so you know by the compiler so it knows the value they are implicitly Const so the values that this is different from you know we'll get to the code later on and then the code gets a little blurry about the constants but here on the value they are implicitly Const you can't change them if you cast away the Const the compiler will let you do this Marshalls not in here Marshall has this great talk about what happens when you get undefined behavior the way I like to do it to talk about it is that if if you set up a situation for undefined behavior you're now allowing your cat the compiler to make your cat have puppies and you may not even have a cat so so undefined behavior is a very dangerous place to go yes you'd have to so the question was is it ok to cast away the cost and then not modify the value you'd have to talk to a compiler guy I prefer not to tread in those areas myself because compiler has this nasty way of biting me when I'm not watching so yeah so thank you so so we've talked about values now oh okay I'm just sorry okay so one of the experts just said that that the question was if you if you cast away the countenance of a Const exper value the question was it can you constant cast away the cost but not modify it and get away with it and the expert says it's okay as long as you don't touch it so but my suggestion would be don't cast it away so that the compiler will stop you if you do by accident touch it once you've cast it away so we're gonna spend most of our time talking about the computations oh and chocolate yeah I can't yeah that but but he brought value no I can't throw it that far someone's gonna have to pass it back we'll do a bucket brigade across so computations so you can declare free functions member functions and constructors as const expert the code that's once you once you put that contacts for declaration on that function or constructor the code that the compiler will allow you to put inside there becomes more constrained you can't put just any code inside of a function or constructor you have to follow the rules the the rules in C++ 11 are pretty highly constrained its but it's the cool thing is it's still C++ in C++ 14 there were some folks who went to some heroic efforts to allow a lot of very cool stuff to be inside of the code and we'll see some examples of that so it's the context for constructor that allows you to make a user-defined literal type that's a little bit counterintuitive when you first hear about context borough there are people who want to declare context per classes so you want to put that context per class whatever that's not the way you do it the way you do it is you take one or more of the Constructors for that class so you can have a class that has one context per constructor and other non cons to expert constructors and if you use that context for constructor you can get a context for literal out of that write a constant literal out of that so if you put Const x4 on the front then that allows the compiler to produce the value from that computation at compile time and that's the cool part again just to reiterate quickly why would you want to do that because you can reduce your runtime execution time you can reduce the program footprint because no longer have to include the code that produces the value you're catching errors at compiler length time and fortunately for me neither herb sutter nor andre are in here but i I think this is probably one of their top quotes for me so there was this interesting word that I used in a previous slide about allowed to be computed at compile time so what what does that really mean well okay if you have a Const exper function that can run at compile time it can also run at runtime so let's let's look at an example of that so here's here's our very first constitu expert function what it does is it takes in a value divides it in two and returns the value it's not a very interesting function but you know you have to start someplace so we can call that function and put the result of that call into a context for value that we're gonna call half and now we can do a static assert on that value that same function because it's it's just standard C++ nothing funny about that code we can call that same function at runtime with a value that the compiler has no idea what the value is going to be okay so we're going to wait until runtime we're going to get the value in our hand because somebody hit that keyboard we're gonna divide it in half now we can't do the static assert I hope it's clear to everybody why you can't do the static assert on a value you don't know until runtime but the compiler will keep track of that difference and part of how it does that is by whether the value of run is not declared cost expert it's just cost but the value of half further up the slide that's a Const extra value yes/no auto will not so the question the question was will auto figure out that the value that's being returned his context for and the answer is know that even though you call a a context per function the general inclination of the compiler will be to not produce context for values unless you demand it so make a point of demanding it as often as you can that's uh see if I can I will try Oh almost got it Beeman yeah so Beeman asked is there a way to poison well half of and the answer is yes mostly and we'll get to that later on that's something yeah and and thank you for that setup yeah we're gonna have to bucket-brigade the chocolate back on this one here so this is going back question could you speak up and try it again so I think the question is whether any of the stuff that we're seeing here is going to prevent the the return value optimization from from working and if you declare a constant value then nothing at runtime nothing gets returned it's already there so there's so you're better off than you would be if if you had the the return value optimization so the the way the way a function supports okay so I'm being advised to move on we are at that would take us off track I was about to go on the on some other stuff which I don't need to thank you okay so we have con sex for evaluation it may be at run time to force that translation happen at or that that evaluation that happened during translation there are two ways within the standard to do that one is to declare the value that receives and it's going slower than I thought the the value that receives it as Const expert that's my favorite way to do it because if you look at it you can see what's going on and you know that the compiler is gonna put it there the next one is to use it where a literal is required by the compiler and this means that you have to be a little bit more aware of you know when does the compiler have to know this for array boundaries this is pretty obvious if you're using it for a template parameter this is pretty obvious there are some other places where it's not quite as obvious but if the compiler says I have to know this value now it will insist on it the context for yes yes so the question is does the constant context for constructor worked the same way and the answer is yes that if you have a an object with a context for constructor and the value that is being constructed is declared as context where it will be determined at compile time or the compiler will tell you it can't determine it so you either get a valid value out of it or you get a compiler error so good question and you get some chocolate and I can't throw it that far could you pass that back thank you so the context for keyword is part of the definition that won't compile because we're seeing two different declarations of Const one of which is context and one is not so when the compiler sees that it'll say and I you can't do that I won't let you do that now if it were to happen in two different translation units the compiler doesn't necessarily get to see that nevertheless don't do it yes yeah so so the question is I think is the context for part of the Declaration of the function so the constant expert is not part of the return type because either a constant value or a non constant value can be returned so okay all right so they are implicitly in line the compiler has to be able to see the definition of the function before anybody invokes it there are a couple of interesting rules regarding contexts for in floating point and yeah so so this one's this one's really interesting that if you have a floating point value or a floating point thing that's being computed by your by your compiler you can run that computation at runtime you can run that computation that compile the compilers not guaranteed to produce the same result from both of those computations does does anybody have an idea why yes perfect so the quest the the issue is that if you're cross compiling you know your floating-point units may be different so the the standards folks gave themselves and appropriate out saying you know if this we can't guarantee this we encourage compiler vendors to to do the right thing and produce the same value but they can't guarantee it so just to be aware if you're doing floating-point computations at compile time in particular the ones that are done at compile time if you have a if your cross compiling and you have a heavy duty processor and you're running on some kind of a wimpy compiler processor the wimpy processor may not give you as good results you know good in quotes depending on which what what you consider to be good the results could be different because the the wimpier compiler is going to struggle a little bit more and maybe allow a little bit furrier results yes yeah so the question is where do you lose your precision and the answer is this entirely implementation too dependent so this year you're in the hands of your compiler vendor yes yeah so the from from one of our GCC experts in the back he says that GCC at least so I'm heads up I'm going to be sending some chocolate back I can't throw it that far so that send that back the GCC folks have been working hard at trying to keep those aligned and it looks like there's another question back there okay and and so Howard gets chocolate for that for sure more chocolate going back heads up so so the point was that you can change the way your floating-point unit works you're you're rounding implementation or whatever at runtime so you can't guarantee under any circumstance even even with a marvelous simulation that the the floating-point computation is going to be exactly the same so the other thing that's interesting a lot of folks who do floating-point computations do that by looking inside of the the raw floating-point literal and you know crawling around in the bits because there's this exponential characteristic of most floating-point implementations and people take advantage of that and Const exper will not let you look inside I've tried you know there may be people who are more clever than I am but I think I think the folks on the standard really nailed this one down it's yeah I know I somebody can tell me they've figured out how to do it but they're doing their darndest to discourage you from looking at the bits in part that's a that's a portability issue because there's no guarantee that some processors representation is going to be I Triple E anything so you know again we're dealing with cross compiling okay okay so yeah yeah so so Peters saying that they're using could you send this chocolate I don't yeah thanks so that it'll taste the same whether it's cracked or not so Peter was saying they use a Java to run their IDE and so they're computing floating point values for C++ and Java so who knows what that representation is so let's look at context per in C++ 11 so we're gonna what are the constraints on a C++ 11 context per function it can't be virtual it has to return a literal type or reference to a literal type the parameters have to be literal types or references to literal types and the body of the function is a single statement one statement that's it and that statement has to be a return okay so this is C++ 11 this is this is where it all starts this is an important point to remember for later unevaluated sub expressions are ignored so what are we going to do with just a return statement okay so we can do compound statements we can do function calls oh yeah somebody said something about the ternary operator what are we gonna use it it's getting louder everybody one two three we got it okay so and we don't we don't hand out chocolate to everybody for that one so let's look at a function so this is we're gonna do the power of a value you know exponential value and we're going to do this we're going to code this so that we can determine at compile time this is since for C++ 11 Const expert and this function just kind of sets us up because we're gonna deal we're gonna allow ourselves to do negative values and so there's the the funny stuff that happens with the power that the negative power of a value is multiplying it by the inverse of the value itself so that's that's really all we're setting up here and up here at the top this is where the recursion happens and it's not very complicated this is all standard C++ code as long as you don't mind a little bit of recursion we're now allowing ourselves to compute the power of a value at compile time okay any questions yes so so the question is the question was whether there are too many cost experts so the first the the lower function the one that says user facing interface that's not recursive okay so what it does is it it takes in the value and it says is the exponent negative or positive okay so the the problem is is the name starts with a context for underscore and you have to pay attention that underscore yes okay so so Peters telling me I should write my code better and I'm sure he is right that that I should be using unary minus and ID there at least two pieces of chocolate that need to head over this direction okay so yeah my code needs to improve I don't have any doubts about that so one of the things that's interesting there's a throw in there what are we going to do with that why is there a throw in a context per function that doesn't seem like something that's going to work at compile time does it yeah and this this compiles but there's a throw what the heck is going on there yes Peter yes okay youyou already got at least two pieces of chocolate yeah yeah so so what what Peter is saying is that it will it will fail to compile because remember earlier there was this yellow strife about unevaluated sub-expressions are ignored the throw as long as it's not evaluated can just sit there benignly let me advance to the next set of slides so that we can walk through the points so this is an idiom for context for code you'll have once there gets to be a lot of context for code in the world you'll be seeing throws in it if you evaluate the throw during compilation then the compiler will stop you dead because it says I can't throw as long as you don't evaluate it it will just sit there and the other part of it is that if it's at runtime because the return value isn't being used where a constant expression is required if you're at runtime then it turns into a legitimate throw so this is a standard way of handling errors with in C++ yes your question yeah okay so the point is that this would be an easy way to find out whether we're getting run time or compile time evaluation and I'm going to have to move faster thank you very much yeah so let me send some chocolate back to you let's see how far back that goes yeah so that that keeps going back so we're hopefully we'll get to the slide where we leverage this yes question the back that's that's a so the question is if you if you have a compiler where you've turned off exceptions what's going to happen here and that's a great question I don't have any experience with that so I can't give you the answer somehow you have to know the way that you would deal with error conditions and work within that so we can use this function that we just wrote we can use it at compile time and you can tell it as compile time because we're using static asserts you can use that same function at runtime because here we've got a value that we don't possibly know what is until a runtime yeah it happens to work for my compiler so the point was I used equal equal on a floating point value and yeah it happened to work from my compiler so a C++ 11 Const exper constructor the parameters have to be literals or references to literals you can't have a function try block the constructor body has to be empty nothing in the constructor body in C++ 11 the basically everything that's not static has to be initialized any constructor that is invoked by the object also has to be con sexpert and every assignment in the initializer list has to be a constant expression so when I think about the way C++ 11 Const expert works I see sort of little compiler little C++ interpreters running there's a C++ interpreter that runs here on function a and it and it invokes another copy of that interpreter when it figures out or when it when it goes to function B and then function B returns a value that gets consumed or passed along through function a to function C so that's that's the way I think about it you end up thinking like a functional programmer so in C++ 11 context were is pretty seriously constrained but if you put some effort into it you can do some some cool stuff so let's get to context per in C++ 14 and C++ 11 it gives you the rules for what you can do and C++ 14 they turned this on its head and they said what the things we can't do and the list is long here I don't want you to memorize it it's two pages of things but it includes things like you can't do new you can't do delete you can't do throw you can't do reinterpret cast you can't do dynamic cast but once you've gotten through that list everything else is fair game the rules are there to protect the interpreter the interpreter doesn't want to be working on anything that it doesn't know what it is so you know in the case of of a context per object 10 minutes boy in the case of a context for object it has to get everything initialized up front and then we'll get to will see in context for functions you can actually modify those values in C++ 14 okay mostly it's like regular code if you were to read it it reads like regular C++ so where we were doing we had two different functions to perform the inversion and we had recursion before we now have a single function and it has the same kind of of in elegance that Peter pointed out earlier I didn't change my coding style so in C++ 14 this is much easier and you know as in terms of maintaining it is it just gets a lot more straightforward you don't need to read this code it's exactly the same code we saw before you know it you use it in exactly the same way question yeah so the question is does it compile faster and the answer is I honestly don't know you know my examples were too small to make a difference but chocolate and then I think yeah so watch watch your head Beamen yeah so the question is why did I not go through and carefully enumerate every entry in that list and and be even figured out my response to that is the reason I don't bother memorizing the list is because the compiler is going to hit me over the head if I try to do something wrong most of the time now if it's in an unalloyed sub expression you can put it's not just throws it can be other stuff in there that doesn't really belong and then you won't find out until you try to evaluate that at compile time so it's not it's not perfect you know protection but it's pretty good it's pretty good it's it's a long list of stuff but it all it's the list makes sense to me and be a minute you already got some chocolate right okay okay we won't hit anybody else with the chocolate so in C++ 14 context for constructors we can now put a body in this makes a huge difference having having the body on the constructor and then this list B is basically saying initialize everything okay so as long as you initialize everything you can now put stuff in the body of the constructor the way I think about the again.i model this as a C++ interpreter but that context has now grown it's not each individual function has its own context the context of lower functions know something about what's happening above that they're all producing a constant value so you end up thinking like a C++ programmer who doesn't have new and I can think like that maybe some of you can't but it works well for me so we have less than 10 minutes and we're going to rip through compile time parsing as our example so let's make a binary literal they don't have a binary literal in C++ 11 can we make one it turns out yes it's a single function yeah it uses recursion but this particular implementation allows you to put commas in your binary literal so you don't want to spend too much time studying that well let's just assume that I have tried that it compiles it runs here's some some example code that uses that compile time binary literal and I spent a bunch of time doing embedded development and boy wouldn't it wouldn't I have ever killed for a binary literal now we've got it and we'll get to this but you know it happens in C++ 14 but you know I really wanted this so oh yeah and it's worth pointing out that I can make a binary double not that's extraordinarily useful thank you so let's do that solve that same problem in C++ 14 it's easier to code than it is in C++ 11 but it's not as useful because in C++ 14 the Standards Committee gave us that that literal so a round of applause for the Standards Committee here thank you very much thank you yes my approval of the Standards Committee so and that's that's the way you would do the binary literal in C++ 14 but the code that you know where we did it with recursion in C++ 11 this is very straightforward and I'm probably just about out of time the example code here is identical to the other example code it runs exactly the same way is there a weakness in that particular implementation well I was taking in a char star can we get rid of the problems of buffer overruns yeah so here's actually I stole this from cpp reference comm so certainly don't you know go to CPP reference comm and look at their context per page this example sitting right there so what it will do is it will take in a char or a literal char array determine the length capture that at compile time or in your in your context per evaluation and and so limit yourself so that you can't walk off the end of your buffer and this is how you would use that so I'm probably just about out of time let's see how fast we can get through this so limits on context per so there's an annex B and the standard that has two statements regarding context but that are really important one is how many what what are the minimum suggested number of recursive invocations that are allowed by context where that's 512 in C++ 14 how many full expressions would be allowed to be evaluated inside of producing a single context per value and that's over a million and the actual limits are up to your compilers so those are recommendations for minimum values whatever your compiler does is what your compiler does how do you do bugs this stuff sometimes you just pull through what I like doing is running the code in the debugger so just because you've declared a function is context per you can still run it at runtime so you initialize a non-literal with the function and then run that in the debugger and compare that to debugging a template okay so I yeah this it's really it really makes a big difference adding print statements however is tough because you always want to put in a print statement in some part that's going to execute and prints since they do i/o they are never context Burgh so you have to make a copy of the function or remove the context or qualifier while you're debugging it if you like to debug with prints but if you've got a good debugger you can get a long way so what's a user error look like at compile time this is what it looks like it's not you know beautiful but at least it stopped you at compile time and it got you into the right area so you'll now look at this throw and maybe there's a clue around the throw about what you did wrong but if you leave the context for off you'll get your throw you won't get that error at compile time it will happen at runtime Peter right yes yeah so if you if you have a static assert then the compiler will stop you because it has to and I'm done right yeah okay I'm so so the time is up I'm not going to shut it down I'm gonna carry on for just a few more minutes and forgive me for that so yeah if you if you're to toss in a static assert then that would be a way of making it happen at compile time oh all right so yeah so you can't static oh sorry I need to move fast so I'm gonna stop handing out chocolate and answering questions let me let me just pull through here really fast so in my opinion runtime execution is really handy for debugging in this particular case it's not so good for debuggers so or r44 excuse me for users so which of those two cases generates a runtime error yeah yeah that's the one that's easier to type because you didn't have to type the Const expert so you get you get punished by a runtime error if you forget the Const expert and that means that every invocation of that function has the potential for error so very quickly getting to Beeman's question from a long time ago is there a way to poison a function and there isn't within the standard but we've got a hack that Howard helped me with who's Howard Howard Hinnant is sitting right next to Beeman so what you can do under most circumstances is so you can put an unresolved symbol in a throw so the throw won't be evaluated here we've got an unresolved simple and we're dropping it into the throat we're using is the text for the throat because and what she'll get out of that is a rather than a compile-time error you'll get a link time error so this is this is what you'll see this is yeah well thank you yeah and this this was actually it took a number of years for her thrashing around to figure out that you know the the standards guys really knew their work they made it very hard to detect to to draw a distinction between run time versus compile time why does it work the throw must not be evaluated at compile time the throw must be included in a runtime implementation and the run time implementation cannot link because there's an unresolved external is this the best you can do it's the best we've found so far the errors ugly doesn't identify the line where the error was and it may not work Richard Smith who's the the brains behind C++ 14 this is a quote from him that the compiler is allowed to include the throw code even though it's not executed if your compiler goes ahead and includes that throw in the in the executable then you're gonna have your link time error so any error will be a false positive so you'll know you know right now either either you screwed up or your compiler isn't isn't taking care of you so the summary for the technique is a context or function has to have a throw in it you declare an unresolved external constant R star and then you reference it and I yeah I kept you guys over time the next room's gonna start I got to call it quits but thank you very much for attending you
Info
Channel: CppCon
Views: 37,809
Rating: 4.6891193 out of 5
Keywords: Scott Schurr, CppCon 2015, Computer Science (Field), Bash Films, Conference Video Recording, Event Video Recording, Video Conferencing, Video Services, C++11, Programming Language (Software Genre)
Id: fZjYCQ8dzTc
Channel Id: undefined
Length: 64min 6sec (3846 seconds)
Published: Fri Oct 09 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.