[try Beta version]
Not logged in

 
best/worst code youve seen?

Pages: 123
Jul 1, 2014 at 6:45am
today i finished writing a working version of my lexer (thank you @albatross, @James2250, @Lachlane) and as i went over it i realized that it was very messy. not poorly written, but not my best. it could also be cleaned up and refactored a lot too. anyways, it got me to thinking... what was the best or worst code youve seen?
Jul 1, 2014 at 6:53am
Hands down best I've seen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<typename Iter>
auto slide(Iter begin, Iter end, Iter target) -> std::pair<Iter,Iter>
{
    if (target < begin) return std::make_pair( target, std::rotate(target, begin, end) );
    if (end < target) return std::make_pair( std::rotate( begin, end, target ), target );
    return std::make_pair( begin, end );
}
 
template<typename Iter, typename Pred>
auto gather(Iter begin, Iter end, Iter target, Pred predicate) -> std::pair<Iter,Iter>
{
    auto start = std::stable_partition( begin, target, std::not1(predicate) );
    auto finish = std::stable_partition( target, end, predicate );
    return std::make_pair(start, finish);
}

For those wondering where these functions came from: https://www.youtube.com/watch?v=lX5tfRdkoY0
Last edited on Jul 1, 2014 at 7:16am
Jul 1, 2014 at 8:09am
Iterator hell ^ LOL
I'm still curious where this C++ programmers love for iterators is coming from.
Last edited on Jul 1, 2014 at 8:10am
Jul 1, 2014 at 9:12am
Iterators are great. Did you know Java has them? Java iterators are underpowered though.
Jul 1, 2014 at 9:45am
@ Lachlan Easton: no offense but they're yucky.

Apparently the language doesn't even allow you to write the proper return type in front, where it belongs. Also if you write auto then why do you need to later write std::pair<Iter,Iter> as well? Yucky yuck.

Back on topic, one of my favorite pieces of C++ code:

1
2
3
4
5
6
template<class ForwardIt>
void selection_sort(ForwardIt begin, ForwardIt end)
{
    for (ForwardIt i = begin; i != end; ++i)
        std::iter_swap(i, std::min_element(i, end));
}


Edit: off-topic again:

rapidcoder wrote:
I'm still curious where this C++ programmers love for iterators is coming from.

I believe it comes from the fact that Iterators allow Containers and Algorithms to be combined like Lego. *tongue-in-cheek*
Last edited on Jul 1, 2014 at 9:51am
Jul 1, 2014 at 10:37am
no offense but they're yucky.

None taken, they're not my functions.
return type in front, where it belongs

And I personally believe types should be on the RHS, but it's really a style choice, perhaps I've been reading too much Sutter http://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/.
I don't know where you're getting "yucky" from :P
Edit: I'm actually surprised that that's the part that made you flinch, 'cuz there's a better way to return from those functions to clean it up(with uniform initialisation) https://gist.github.com/LBEaston/43cfa0961437f76c2ad3
Last edited on Jul 1, 2014 at 10:45am
Jul 1, 2014 at 10:41am

Iterators are great


Iterators are useful, but enough useful to base the whole standard library on them.


I believe it comes from the fact that Iterators allow Containers and Algorithms to be combined like Lego. *tongue-in-cheek*


Only some algorithms. Some algorithms require several passes over data or random access, and then iterator concept does not fit naturally. And it breaks totally for parallel algorithms (but this is not a problem, as long as the standard library does not offer anything here)

Last edited on Jul 1, 2014 at 10:43am
Jul 1, 2014 at 10:51am
Some algorithms require several passes over data or random access, and then iterator concept does not fit naturally.

I'm having trouble seeing how o_O
And it breaks totally for parallel algorithms

Do you have any resources explaining why this is? What alternatives are there?
Jul 1, 2014 at 1:02pm
closed account (10X9216C)
rabidcoder wrote:
And it breaks totally for parallel algorithms (but this is not a problem, as long as the standard library does not offer anything here)

Breaking news, a single design pattern isn't a one size fits all.

CatFish wrote:
Also if you write auto then why do you need to later write std::pair<Iter,Iter> as well?

Putting it on the right hand side puts it in scope of the function.

1
2
3
4
5
6
7
8
9
10
11
class SomeClassName
{
    struct SomeOtherName;

    SomeOtherName foo();

};

auto SomeClassName::foo() -> SomeOtherName { }
// vs
SomeClassName::SomeOtherName SomeClassName::foo() { } 

Jul 1, 2014 at 1:05pm
Lachlan Easton wrote:
I'm having trouble seeing how o_O

I am unsure how to word my thoughts, so I'll just paste the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <algorithm>
#include <iostream>
#include <list>

int main()
{
    std::list<int> li{ 2, 30, -29, 30, 10, 11, -100 };

    std::sort(li.begin(), li.end());

    for (int i : li)
        std::cout << i << ' ';

    std::cout << std::endl;
}

Jul 1, 2014 at 1:48pm
That's less a limitation of iterators than it is a limitation of lists.
Jul 1, 2014 at 1:59pm
incidentally, the 70+ old algorithms that were parallelized and all new parallel algorithms in the TS (reduce, inclusive_scan, exclusive_scan) use iterators.
Last edited on Jul 1, 2014 at 3:39pm
Jul 1, 2014 at 2:18pm
Lachlan Easton wrote:
That's less a limitation of iterators than it is a limitation of lists.

And by extension, it's a limitation of list iterators.
The example shows how iterators cannot always separate the container from the algorithm. QED?

myesolar wrote:
Putting it on the right hand side puts it in scope of the function.

I thought the technical reason has to do with Iter being a dependent name, or something. I admit that I didn't try compiling the code.

But the point of my question was implying that auto should be enough by itself once used, as below, without the noise of ->pair<>:

1
2
3
4
5
template<typename Iter>
auto slide(Iter begin, Iter end, Iter target)
{
    // ...
}

Jul 1, 2014 at 4:47pm

Breaking news, a single design pattern isn't a one size fits all.


True. And C++ used this single pattern as the main design pattern of all the container library, forcing every concept that is not really an iterator be iterator. They had to overload iterator meaning to allow for random-access iterators or bidirectional iterators. Ugly as hell. Random-access iterator is used for the "random access" part, not for the "iterator" part. A side effect is that now you have to remember which iterator types work with which containers and it is even not clearly visible in the API. And you also have to give a pair of iterators everywhere where you really mean passing a collection (even Java iterators don't have this limitation - one iterator is enough).

Well-designed libraries provide iterators as part of them and then allow to perform *some* algorithms that are natural on iterators like filtering or mapping, but not sorting. Therefore you know the iterator is just an iterator and the algorithm on iterator will iterate data once. Algorithms that need other types of containers, just... guess what... get other collections as arguments. E.g. quick-sorting makes sense on random-access sequences and k-means makes sense on iterable things (iterable = something that can create an iterator to do multiple passes).

Last edited on Jul 1, 2014 at 4:52pm
Jul 1, 2014 at 7:21pm
rapidcoder wrote:
C++ used this single pattern as the main design pattern of all the container library, forcing every concept that is not really an iterator be iterator.
Guess what Java does with classes ;p
Jul 1, 2014 at 7:31pm
My favorite piece of code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
float Q_rsqrt( float number )
{
	long i;
	float x2, y;
	const float threehalfs = 1.5F;
 
	x2 = number * 0.5F;
	y  = number;
	i  = * ( long * ) &y;                       // evil floating point bit level hacking
	i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
	y  = * ( float * ) &i;
	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//      y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
 
	return y;
}


From Quake 3

http://en.wikipedia.org/wiki/Fast_inverse_square_root
Jul 2, 2014 at 1:31am
closed account (10X9216C)
True. And C++ used this single pattern as the main design pattern of all the container library, forcing every concept that is not really an iterator be iterator.

Indeed it's not perfect, indeed it could be better, but it works for what's needed. If it fails, there is usually a boost library somewhere that compensates for it. Stop moving from argument to argument, we all know you hate C++ senselessly, as most of us hate Java senselessly, leave your C++ senselessness for your Java forarms.
Jul 2, 2014 at 1:50pm
Who told you I hate C++ more than I hate Java? This is C++ forum so we're discussing ugly code in C++. If it was a Java forum, we'd discuss ugly code in Java.
Jul 2, 2014 at 2:01pm
closed account (10X9216C)
Who told you I hate C++ more than I hate Java?

You did?

This is C++ forum so we're discussing ugly code in C++

So why do you keep bringing up Java? Stop trying to deflect.
Jul 2, 2014 at 4:34pm
Maybe he brings up bad C++ code in Java forums.

Anyways to add on the iterator discussion, I honestly have been lacking on using them until recently. I usually used to just write my own STL implementation until I realized how useless it was.
Pages: 123