Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
That Turkey Story
Mar 30, 2003

Victor posted:

Clearly, return is a function. :psyduck:

A little side story -- I've seen someone do this before when he was first learning to program and when I told him that he didn't need the parenthesis because return is not a function, he said that he was using the parenthesis not because he thought it was a function but because he wasn't sure of the order of operations. For instance, he thought return 1 + 3; might return the value 1 and then the rest of the expression was evaluated "after the return" and therefore not affecting the return value (in other words he thought return 1 + 3 could potentially behave something like (return 1) + 3 where "return 1" returned the value 1 and had a value in the encapsulating expression of 1). I was kind of puzzled for a second, but I was actually sort of impressed when I heard his rationale since it showed both that he questioned the effect of a type of return statement he had never seen before, as up until then he probably had only seen 1 term return statements, and he also realized that by using parenthesis there he could more safely assume the result that he wanted. He is now actually a very good programmer!

Of course, that was someone who had only just started programming a week before, so he had an excuse to not know the behavior, and if I saw any experienced programmer doing it I'd definitely be a little bit more baffled (though honestly who really cares, some extra parenthesis never hurt anyone).

Adbot
ADBOT LOVES YOU

That Turkey Story
Mar 30, 2003

more falafel please posted:

It's better than
code:
if(something){
  DoWork();
^^ TWO loving SPACES EVEN THOUGH THE REST OF THE PROJECT USES TABS
}else{
  DoOtherWork();
}

Holy moly fucckkkk!!!!!!!!!! Uggg I just want to kill myself! Yuck! Two loving spaces? God dammit!

poo poo...

That Turkey Story
Mar 30, 2003

Zombywuf posted:

Yuck. I'd like to plead on behalf of all maintenance programmers everywhere that you don't do that.

Also, why should it not be possible to call a member of a null object?
code:
#include <iostream>

class foo {
public:
  bool is_null() {
    return this == 0;
  }
};

int main() {
  foo *a = 0;
  std::cout << a->is_null() << std::endl;
}
Works fine in C++. This works for exactly the same reason as the above D flat code, but you at least know where to find is_null in this case.

No it doesn't. That code has undefined behavior. It is never safe to invoke a non-static member function through a null pointer.

That Turkey Story
Mar 30, 2003

Yeah, even PODS.

That Turkey Story
Mar 30, 2003

more falafel please posted:

I understand why "undefined behavior" generally means no-no, but in cases like this it doesn't matter what the standard says to some degree, because it works with the only way you would implement POD types.

Undefined behavior isn't "generally a no-no" it's always a no-no. It does matter what the standard says. We all know what the probable implementation will do, but that doesn't mean you should ever rely on it, especially here since there's no reason to.

That Turkey Story
Mar 30, 2003

forelle posted:

I have a real objection to the "It can never be NULL here so I'm not going to check for it." idea. Adding checks tells me (the maintainer) that these pointers should never be NULL and if they are, something is hosed up.

You should always check every pointer before dereference through it, even if you believe with your whole heart it can never be NULL, because you're often wrong.

I completely disagree with this, unless you mean checks that only exist when compiling a debug build such as an assert. If by context your data can never be in a particular state, checking for that state in a release build every time that bit of code is run is just silly. For example, if I'm writing an iterator for something like a linked list, I'm not going to check at every increment or decrement if the pointer I'm dereferencing is NULL. Write proper unit tests rather than flooding your applications with redundant checks that you often can't do anything appropriate about if they fail anyway. If you really want to just inform the reader of the code that the data can't be NULL there as you claim, then use a comment rather than introducing a runtime check.

That Turkey Story
Mar 30, 2003

zootm posted:

This is largely correct but the essential point here is that goto should be limited to the point where execution paths can be easily determined. Gotos within local scope for breaking out of loops and the like are theoretically fine, but jumping between functions, jumping to arbitrary points to emulate flow control, and so on is craziness. There's definitely valid uses within C from what I've seen, though.

Amen. I can't remember when I've ever used a goto, but specifically for jumping out of multiple levels of loops/switches it is pretty much the only solution other than possibly a return statement in some languages (yes in OO-code too). Multi-level or labled breaks are great, but again, unfortunately not all languages have that option (*cough* C, C++). In those cases, goto can be the "correct" thing to do.

Don't get caught into a religious hatred of a particular language feature; it's the naive way of becoming a better programmer. Prematurely ruling out a tool like goto may help you decide more quickly on an implementation for whatever it is you are trying to do since you are decreasing your number of options, but sometimes you may be needlessly throwing away the perfect tool for the job. I'm an atheist, deal with it.

Zakalwe posted:

Here's another coding horror. A student of mine refused to use a for loop. He wrote everything as a while loop


for(int i=0; i<5; ++i){
do_stuff(i);
}

was

int i=0;
while(i<5){
do_stuff(i);
++i;
}

If that's the worst of your problems when teaching a programming class then you're doing a very good job :p

That Turkey Story
Mar 30, 2003

floWenoL posted:

Modern (non-lovely *cough*) languages like Java and Perl provide labeled loops and ways to break out of them, so that removes one of the two remaining use cases for gotos nowadays, and exceptions remove the other one.

Whoa, whoa, backup. Are you saying Java isn't a lovely language?

That Turkey Story
Mar 30, 2003

Vanadium posted:

I got pretty much as far, except I did the recursion by composition and not inheritance, but then I tried to wrap boost::call_traits<T>::param_type around everything to avoid needless copying and it all fell apart. :(

It would be impossible to deduce T in an expression like that because you'd be trying to deduce an unknown metafunction's nested type. The purpose of call_traits is for times when T is already known, for instance if T is a template parameter of a class and you wish to use call_traits to determine the parameter type to be used for a member function which takes a T. std::forward in 0x actually uses this behavior to its advantage to make it so that you have to explicitly specify the template instantiation when using it (its parameter type is based on the evaluation of an identity metafunction of the specified type).

That Turkey Story
Mar 30, 2003

floWenoL posted:

Wrong-o. I'm saying that the writer of functions should be documenting whether their functions handle NULL or not. And if the writer of the function is indeed an idiot and didn't specify the behavior, well, then you (the maintainer) can assume it doesn't; the result will be no worse than that in the reference case (since a "NULL" reference is undefined).

So in other words you get exactly the same behavior when using a pointer except that with a reference you know that an object must be passed based simply based on the parameter type whereas with a pointer you only know if you read further documentation.

That Turkey Story
Mar 30, 2003

floWenoL posted:

You get behavior that is *no worse* than using a reference and potentially more readable. :P

I kind of regret bringing this up because it always turns into a shitfest. Honestly, if it's for your own personal project or whatever it doesn't really matter. Didn't we come to an agreement the last time? You mentioned some sort of syntax like "Foo(bar, out(baz))" and I think something like that would be fine if it were applied to the standard libraries (which is a pipe dream, I guess).

Yeah. I think in the very least we did agree that it would be nice if in certain cases you explicitly label the out parameter when you pass an argument, such as by using something like a boost-style reference wrapper. My stance aside from that, and the reason I prefer references in the absence of a reference wrapper, is that I believe the parameter type should as closely match the purpose of the parameter as possible and tell as much information as possible about its use. A reference has more strict requirements than a pointer, so at least for me, it is more clear of the intent of that parameter if it uses a reference than if it uses a pointer. In either case with a pointer type, you at least wonder if a null pointer is valid (that case doesn't even have to pop into your head with a reference). In the end, I'd much rather see a more specific type than a pass by pointer just for a convention to show an out-parameter and I think that's where we disagree.

floWenoL posted:

No it doesn't. That's silly.

I would at least assert it just like you might do with any function's simple preconditions.

That Turkey Story fucked around with this message at 01:21 on Sep 2, 2008

That Turkey Story
Mar 30, 2003

Karanth posted:

code:
int big_number(int thousands, int ones);
int big_number(int millions, int thousands, int ones);
...
code:
num < big_number(5,000,000)
:downs:

That won't work, but if you're sly, you can do it with that syntax using macros :clint:

That Turkey Story
Mar 30, 2003

shrughes posted:

floWenoL is just wrong.

This. Take whatever floWenoL says with a grain of salt, he's not very smart and he loves to mislead people by giving purposely false information. If all of your functions aren't less than 10 lines you probably made a huge mistake/are a terrible programmer. He's also really freakin gay.

That Turkey Story
Mar 30, 2003

shrughes posted:

Well regarding 3000 line functions, they're only sensible when the level of complexity is very low, like when 2975 lines are used to fill a static array.

Metaprogram that poo poo, bitch.

That Turkey Story
Mar 30, 2003

Contero posted:

My girlfriend :smug: wrote this:

code:
for (j = 0; j < 15; j = j++) {
   ...
}
Which took a while to explain why j = j++; is pretty much the same as saying j = j;.

UraniumAnchor posted:

Fixed that for you.

You're both wrong, it's undefined behavior because you're modifying j multiple times between sequence points.

Edit: Oh, nm didn't realize it was java

That Turkey Story fucked around with this message at 00:44 on Feb 16, 2009

That Turkey Story
Mar 30, 2003

Fehler posted:

I actually had a good reason for this as well, as there was gonna be a final else that handled all lines after the third one.

If you think that was a good reason to do this you need to quit programming forever!

That Turkey Story
Mar 30, 2003

rjmccall posted:

The important point here is that you're not supposed to repeatedly assume the globalness of a singleton; if every access to the singleton goes through the global accessor, you're completely sabotaging this advantage of the pattern. Instead, you should have only a few places in the code that read the global reference, and those places should pass around the reference to everything else that needs it. That way, you only need to modify those few places if the data ever becomes global.
Quoted for truth. I go so far as to say ditch the entire concept of direct global access completely and instead favor a monostate pattern with an interface and associated behavior that allows an internal implementation using either a shared global resource or an owned implementation, where the distinction is specifically designed to be an implementation detail. I.E. Consider a memory allocator that uses a shared memory pool for all allocations that you instantiate like any other type -- you just do some_allocator_type my_allocator. Instead of implementing your type as a singleton with a global access point simply because it uses an internal shared, global pool for all allocations, just implement it as any other type except that it internally has a shared state, given that the shared state can be viewed as an implementation detail by design.

For instance, if designed correctly, declaring multiple "some_allocator" objects should work fine even though they may all use the same, shared, global pool underneath. Given its interface, which would include basic operations like allocating an deallocating blocks of memory, there should be no problem if at some point in time you decide to go back and change the type to use an individual pool per object. If you are using some static "get_instance" function to access your object instead of what I describe above, you can still use it appropriately as long as you only call "get_instance" in the same places you would logically grab a new instance of the type as though it were a factory. Once you obtain your object, pass it around like you would any other object (don't keep calling get_instance). The fact that only one instantiation actually exists should be an implementation detail. Using a monostate instead of an explicit global access point just makes proper usage more consistent with other types (and even more usable with generic code).

In my opinion, what it all boils down to is that if your desired use of a singleton is based around the fact that you can provide global access to a single object, you're just making a pretty global, which is fine if that's what you want, but don't think you're making things any different by attaching a fancy name to it. All too often I see people say "man, I hate globals, I use singletons instead" and then proceed to use it as a global without giving it a second thought.

That Turkey Story
Mar 30, 2003

Kelson posted:

Your post took a couple readings to hash out the actual meaning... and I've yet to see a pretty name for a singleton, just hugely long names with multiple colons. Interesting design perspective though, do you have any examples?

I'm pretty sure I gave an example.

That Turkey Story
Mar 30, 2003

Here's a wall of text for you:

Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer Ugg boots is a lovely programmer

That Turkey Story
Mar 30, 2003

Steve French posted:

Well hey, at least it isn't
code:
i = (i++) % j;

Both statements have undefined behavior unless those are overloaded operators. Post or pre-increment doesn't matter, assuming C or C++, that is.

That Turkey Story
Mar 30, 2003

Dijkstracula posted:

That pleb coder, he neglects the case where p_destination is both not equal to zero and not not equal to zero :pseudo:

You joke but that's actually the common case on X/329-compliant systems.

That Turkey Story
Mar 30, 2003

Lexical Unit posted:

In case y'all were curious, here are the lines of code that lead me to inspect the byteswap header file in the first place,
code:
vector<complex<float> > payload;
b.get_payload (payload);
// Do we need to byteswap here??
for (int i = 0; i < payload.size (); i++)
  ByteSwap (payload[i]); // why doesn't this work?!?!
:toot: Yes, those comments were checked in.

God dammit people are stupid.

That Turkey Story
Mar 30, 2003

Blue Footed Booby posted:

Even ignoring what's in the standard library (I don't know poo poo about C++ either) he managed to make the function name by itself more characters than doing it the "hard" way instead of just calling it "toRads" or something. :smithfrog:

What? That's not a coding horror at all, he was just being descriptive. The benefits of functions and abstraction are far greater than saving keystrokes.

That Turkey Story
Mar 30, 2003

tef posted:

from my experience most programmers do not handle any form of integer overflow. (and sometimes they do things like if (i > INT_MAX)

I've seen stuff like that a lot. This and misuse of floating point types really bothers me for some reason. It's just so fundamental. So many people just foolishly label these issues as "purely theoretical" rather than "subtle, scary bugs".

That Turkey Story
Mar 30, 2003

BP posted:

Extra bonus horror: the fix we are putting in place is to stop using the encrypted form of the RPC. This is because the "encryption" on the RPC is actually just a keyless transposition/obfuscation, not any real form of encryption. The core team didn't really share this with anyone--we've been transmitting sensitive data with essentially zero security for years.

Haha, saw this coming a mile away.

That Turkey Story
Mar 30, 2003

Beef posted:

Apparently, you cannot initialize an array in an ctor's initializer list. The syntax simply does not allow it.

You can initialize them fine in C++11. Are you using GCC? I believe it supports it already.

code:
your_constructor( your params )
  : your_array { array, or_, aggregate, initialization }
{
  // your constructor body
}

That Turkey Story
Mar 30, 2003

Lonely Wolf posted:

gah just make a thread about licenses already.

Yeah, seriously, this is getting way off topic. Besides, everyone should be using the Boost Software License anyway.

That Turkey Story
Mar 30, 2003

Beef posted:

not in 4.5.x :(

Support has been there at least since 4.6 (4.7 was released yesterday).

Beef posted:

I cannot find the reference to that proposal, is it non-static data member init ?

No, it's Uniform Initialization.

That Turkey Story
Mar 30, 2003

He probably just said it in the manner that you'd expect a goon would.

That Turkey Story
Mar 30, 2003

revmoo posted:

I mentioned in passing that you should probably have server-side validation for a forms infrastructure that runs behind several hundred websites. Apparently development is 'sensitive' and it's offensive to mention things that could or should be done in a different manner. Yesterday I had the director of software development have a meltdown at my desk because I said something about code comments. I'm going to start looking for something else.

In my anecdotal experience, this is not uncommon. You have to be extremely tactful when you point out problems. Programmers are mostly little babies with gigantic egos. Yes, it sucks, but you always have to be mindful of this.

That Turkey Story
Mar 30, 2003

Optimus Prime Ribs posted:

Saw this posted on a different message board:

*snip*

I... :stare:

Good thing those end braces are commented, otherwise I'd be completely lost!

That Turkey Story
Mar 30, 2003

Aleksei Vasiliev posted:

I'm pretty sure there are IDEs that maintain comments like that automatically. I don't know why anyone thinks it is useful.

Agreed. The only time I've ever found notation like that to be useful is with nested namespaces. Sometimes I'll be 2 or 3 namespaces deep and close out back one or two for a declaration or specialization or something. In most other cases, blocks are so small that you can easily see exactly what they correspond to, unless you have some gigantic, several hundred line block of code... in which case you should probably split it up anyway.

That Turkey Story
Mar 30, 2003

baquerd posted:

I like him, seeing if statements without curly braces makes me angry because it's always an if statement I want to add a line to and then I need to add them anyway. Also it just looks plain wrong when braces are in the language.

Sorry, but you are a spergy little baby.

That Turkey Story
Mar 30, 2003

Dicky B posted:

No, feeling strongly one way or another about it is retarded.

Exactly this. If you are sperging out over little subjective stuff then I don't know what to say.

That Turkey Story
Mar 30, 2003

baquerd posted:

Come on, I bet you have at least one little thing that doesn't effect functionality that you greater prefer. Braces style? White space? Variable or function name convention?

I'd go as far to say that if you don't have something like that you're weird.

Sure I'm consistent in my personal work with my preferred style, but I'm not going to get angry when I have to work with different coding conventions.

That Turkey Story
Mar 30, 2003

Haystack posted:

That's almost cute, in a pathetic sort of way.

That's wh...

That Turkey Story
Mar 30, 2003


Don't blame Boost, that's the only way you can do it in the preprocessor!

E: Also, that includes compiler workarounds.

That Turkey Story
Mar 30, 2003

If you think preprocessor metaprogramming is a horror, you can check out my "horror" contributed to Boost for representing binary literals in C++98/03 and I guess technically C though I haven't tested it:

The docs.
The code.

Now that C++11 has user-defined literals, I'll probably update the implementation for compilers that can support it, but that gigantic macro is still going to be there for old compilers.

Edit: To be clear, the reason why preprocessor metaprogramming libraries are so hairy is because the preprocessor can neither recurse nor loop. Since it can't, the libraries have to be written with seemingly redundant macros. Boost.Preprocessor exists as a way to simulate algorithms and datastructures so that higher-level code can "loop" and do other high-level things without needing to have any redundancy themselves.

Keep in mind that the only thing you can do inside of a macro definition is expand other macros, concatenate tokens, turn arguments into strings, and ... welp that's basically it, and that last one doesn't really help during preprocessing (note that I didn't say add, subtract, do bitwise operations, branch, etc. because even those have to be simulated). From those simple pieces of functionality you can produce a library that simulates several different datastructures and algorithms -- Paul Mensonides's Chaos library even has lambda functions.

That Turkey Story fucked around with this message at 18:34 on Mar 30, 2012

That Turkey Story
Mar 30, 2003

Rocko Bonaparte posted:

How'd you get involved in Boost stuff anyways?

I don't know. When I started using Boost, which was probably 8 years ago or so now, I was immediately amazed at what the libraries were capable of and how they managed to get such simple interfaces, so I started striving for my code to be Boost quality. The release after I started using it, enable_if was added and it completely changed the way I thought about C++. That made me join the dev mailing list, mostly because I wanted to be on the cutting edge. Then I just started participating.

When I added BOOST_BINARY it was sort of by accident. What happened was someone else proposed a template metafunction to represent binary values and it was in the review queue (which, believe it or not, was an even bigger hack than the preprocessor hack). The way it worked was you'd do something like binary< 1001, 0101, 0110 >::value to get the binary value 100101010110. The reason why I say it was even hackier than the macro solution is because you have to notice that 0101 is actually an octal value (since it starts with 0) whereas 1001 is a decimal value, etc. So in order for the metafunction to work, it had a whole slew of weird explicit specializations for decimal and octal values that each converted the corresponding argument to what it would be if the value were binary, then combined all of the arguments together appropriately.

It was cool in that it worked, but it was really sketchy, instantiated a lot of templates, and didn't let you use suffixes or anything, so I asked why they didn't prefer a macro solution and posted some quick, hypothetical syntax. People liked the idea so a few days before the review I implemented the macro, posted it to the mailing list, and it ended up getting pulled into the review along side the template. Ultimately mine was the one that got voted in.

Adbot
ADBOT LOVES YOU

That Turkey Story
Mar 30, 2003

Internet Janitor posted:

For comparison, here's somebody else's C implementation based on the spec:
https://github.com/swetland/dcpu16/blob/master/dcpu.c

Pack it up, Notch.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply