Wizzup's ego gets in the way a lot. According to Wizzup in IRC, C++ is weaker than C; it is evil; it is hard, it is bad. It is worse than Pascal and Go-Lang.
I disagree with him, he bans me from IRC.
What I said to him:
YOU find the language hard because YOU lack the skill in it. Doesn't make the LANGUAGE itself hard or bad or evil.
He says HARD is objective and not subjective. No it is subjective. We find something hard because we don't know it that well. Simple. We find math or guitar or physics or whatever it is, hard because we don't know it quite well or as well as we would like. Someone skilled in math will not say it is hard. It's a discipline and takes time and effort and practice to learn. Apparently, my guitar analogy went over his head and is irrelevant because it has nothing to do with languages.
He replies:
No C++ is not bloated unless YOU make it bloated. The same code that is written in C to accomplish what can be done in C++ would be just as bloated and he doesn't understand that. C++ compile pure C code if you wish as well.
I tell him that a sort function in C++ will out perform a sort function in C quite easily. His response:
Let me prove that wrong right now. For the 1 millionth time.
Take for example a sort function in C:
C Code:
bool IntComparator(void* a, void* b)
{
return *((int*)(a)) < *((int*)(b));
}
bool CharComparator(void* a, void* b)
{
return *((char*)(a)) < *((char*)(a));
}
bool FloatComparator(void* a, void* b)
{
return *((float*)(a)) < *((float*)(b));
}
//function for swapping every single byte of a specified type.
void ByteSwap(uint8_t* a, uint8_t* b, size_t size_ptr)
{
int i;
uint8_t t = 0;
for (i = 0; i < size_ptr; ++i)
{
t = a[i];
a[i] = b[i];
b[i] = t;
}
}
//Sort function taking comparators
void Sort(uint8_t* list, size_t length, size_t size_ptr, bool (*comparator)(void* a, void* b))
{
int size = length * size_ptr;
size_t i, j;
for (i = 0; i < size; i += size_ptr)
{
for (j = 0; j < size - i - size_ptr; j += size_ptr)
{
if (comparator(&list[j + size_ptr], &list[j]))
{
ByteSwap(&list[j + size_ptr], &list[j], size_ptr);
}
}
}
}
int main()
{
}
Notice all the comparator functions you have to write and one is required for EVERY single type you want to sort. Each of these if not inlined has an overhead of preserving the stack and dereferencing a bunch of pointers. Not to mention a function call every loop.
The assembly generated WITH gcc-4.8 -O2 optimisations and -masm=intel (and an empty main):
ASM Code:
IntComparator(void*, void*):
mov eax, DWORD PTR [rsi]
cmp DWORD PTR [rdi], eax
setl al
ret
CharComparator(void*, void*):
xor eax, eax
ret
FloatComparator(void*, void*):
movss xmm0, DWORD PTR [rsi]
ucomiss xmm0, DWORD PTR [rdi]
seta al
ret
ByteSwap(unsigned char*, unsigned char*, unsigned int):
xor eax, eax
test edx, edx
je .L4
.L8:
movzx ecx, BYTE PTR [rdi+rax]
movzx r8d, BYTE PTR [rsi+rax]
mov BYTE PTR [rdi+rax], r8b
mov BYTE PTR [rsi+rax], cl
add rax, 1
cmp edx, eax
ja .L8
.L4:
rep; ret
Sort(unsigned char*, unsigned int, unsigned int, bool (*)(void*, void*)):
push r15
mov eax, esi
imul eax, edx
push r14
mov r14d, edx
push r13
push r12
push rbp
push rbx
sub rsp, 24
test eax, eax
mov DWORD PTR [rsp+12], eax
je .L10
sub eax, edx
mov rbx, rdi
mov r12, rcx
mov DWORD PTR [rsp+4], eax
mov DWORD PTR [rsp+8], edx
.L12:
xor r13d, r13d
.L18:
cmp r13d, DWORD PTR [rsp+4]
jae .L26
.L17:
mov r15d, r13d
add r13d, r14d
mov ecx, r13d
add r15, rbx
lea rbp, [rbx+rcx]
mov rsi, r15
mov rdi, rbp
call r12
test al, al
je .L18
test r14d, r14d
je .L18
xor eax, eax
.L16:
movzx esi, BYTE PTR [rbp+0+rax]
movzx edi, BYTE PTR [r15+rax]
mov BYTE PTR [rbp+0+rax], dil
mov BYTE PTR [r15+rax], sil
add rax, 1
cmp r14d, eax
ja .L16
cmp r13d, DWORD PTR [rsp+4]
jb .L17
.L26:
mov edx, DWORD PTR [rsp+8]
sub DWORD PTR [rsp+4], r14d
mov eax, edx
add eax, r14d
cmp DWORD PTR [rsp+12], edx
jbe .L10
mov DWORD PTR [rsp+8], eax
jmp .L12
.L10:
add rsp, 24
pop rbx
pop rbp
pop r12
pop r13
pop r14
pop r15
ret
main:
xor eax, eax
ret
Now consider the same sort function in C++:
C++ Code:
template<typename T, bool low_to_high>
void Sort(T* x, size_t size)
{
for (size_t i = 0; i < size - 1; ++i)
{
for (size_t j = 0; j < size - i - 1; ++j)
{
if (low_to_high ? x[j] > x[j + 1] : x[j] < x[j + 1])
{
T temp = x[j];
x[j] = x[j + 1];
x[j + 1] = temp;
}
}
}
}
int main()
{
}
Assembly generated using g++-4.8 -O2 optimisations and -masm=intel (and an empty main):
OH? Wth? Unfair you say? Fine.. lets use the function and give C a small advantage (C++ compiler optimises out the unused functions unlike C's):
C++ Code:
int main
(){ int arr
[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Sort
<int, true
>(&arr
[0], 10); printf("%d", arr
[0]);}
Assembly generated with g++-4.8 -O2 optimisations and -masm=intel:
ASM Code:
.LC0:
.string "%d"
main:
sub rsp, 56
mov r8d, 9
mov DWORD PTR [rsp], 1
mov DWORD PTR [rsp+4], 2
mov DWORD PTR [rsp+8], 3
mov DWORD PTR [rsp+12], 4
mov DWORD PTR [rsp+16], 5
mov DWORD PTR [rsp+20], 6
mov DWORD PTR [rsp+24], 7
mov DWORD PTR [rsp+28], 8
mov DWORD PTR [rsp+32], 9
mov DWORD PTR [rsp+36], 10
.L2:
mov rdx, rsp
xor eax, eax
jmp .L6
.L4:
add eax, 1
mov esi, DWORD PTR [rdx]
mov ecx, eax
lea rcx, [rsp+rcx*4]
mov edi, DWORD PTR [rcx]
cmp esi, edi
jle .L3
mov DWORD PTR [rdx], edi
mov DWORD PTR [rcx], esi
.L3:
add rdx, 4
.L6:
cmp eax, r8d
jne .L4
sub eax, 1
mov r8d, eax
jne .L2
mov edx, DWORD PTR [rsp]
mov esi, OFFSET FLAT:.LC0
mov edi, 1
xor eax, eax
call __printf_chk
xor eax, eax
add rsp, 56
ret
Guess what? The C++ version has no overhead compared to the C version AND it requires no comparator functions. In fact, since the sort function is generated at compile time in C++, that inner branch for tenary operator is optimised out (the operator used for determining whether to sort in ascending or descending order within the if statement). Doing this in C requires that you write a whole other comparator function to sort in ascending and descending order. Again, LESS code, LESS bloat, faster calculations, inlined and its generic. I'd easily rub it in Wizzup's face but I'm not that kind of person. I'll leave the high ego alone.
Lets take a look at the power of templates.. Something that can NEVER be done in C:
C++ Code:
template
<std
::int64_t number
>struct is_perfect_square
{ private
: static inline constexpr bool is_perfect
(std
::size_t sq
= 0) { return (sq
* sq
== number
) || ((sq
* sq
< number
) && is_perfect
(sq
+ 1)); } public
: enum {value
= is_perfect
()};};template
<std
::int64_t number
>struct is_perfect_cube
{ private
: static inline constexpr bool is_perfect
(std
::size_t cb
= 0) { return (cb
* cb
* cb
== number
) || ((cb
* cb
* cb
< number
) && is_perfect
(cb
+ 1)); } public
: enum {value
= is_perfect
()};};template
<std
::int64_t number
, std
::int64_t exp
>struct is_perfect_n
{ private
: static inline constexpr std
::int64_t cpow(std
::int64_t base
, std
::int64_t exponent
) { return exponent
? base
* cpow(base
, exponent
- 1) : 1; } static inline constexpr bool is_perfect
(std
::size_t n
= 0) { return (cpow(n
, exp) == number
) || ((cpow(n
, exp) < number
) && is_perfect
(n
+ 1)); } public
: enum {value
= is_perfect
()};};template
<std
::int64_t T
>struct is_prime
{ private
: static constexpr std
::int64_t compute
(std
::int64_t Num
, std
::int64_t I
= 2) { return I
* I
> Num
? true : Num
% I
? compute
(Num
, I
+ 1) : false; } public
: enum {value
= compute
(T
)};};template
<std
::int64_t number
>struct Factorial
{ private
: static constexpr std
::int64_t compute
(std
::int64_t num
) { return num
? num
* compute
(num
- 1) : 1; } public
: enum {value
= compute
(number
)};};template
<std
::int64_t T
, std
::int64_t U
>struct concatenate_integral
{ template
<std
::int64_t Limit
, std
::int64_t Num
= 1, bool Cond
= false
> struct calc_power
{ const static std
::int64_t value
= calc_power
<Limit
, Num
* 0xA, (Num
> Limit
)>::value; }; template
<std
::int64_t Limit
, std
::int64_t Num
> struct calc_power
<Limit
, Num
, true
> { const static std
::int64_t value
= Num
/ 0xA; }; enum {value
= T
* calc_power
<U
>::value + U
};};template
<std
::int64_t T
, std
::int64_t U
>struct GCF
{ private
: static constexpr std
::int64_t compute
(std
::int64_t X
, std
::int64_t Y
) { return Y
? compute
(Y
, X
% Y
) : X
; } public
: enum {value
= compute
(T
, U
)};};template
<std
::int64_t T
, std
::int64_t U
>struct LCM
{ enum {value
= T
* U
/ GCF
<T
, U
>::value};};
What is that? Oh yeah that's right.. COMPILE-TIME math.. What does this mean? The code above has ZERO overhead. ALL the results can be calculated at COMPILE-TIME. This can NEVER be done in C. This sort of optimisation is what the Eigen Math library is based off of. If done in C, the above will have the RUN-TIME overhead of a function call AND the calculations. Transposing matrices, any sort of intense calculations can have a lot of its overheads removed at compile-time in C++.
Wizzup seems to disagree. I call it a lack of skill. He takes an offence to anyone calling out his skills. So I said he's emotionally unstabled for taking offence to me calling out his skill and comparing his argument to the Linus Torvald's. I don't care about this alpha male crap. Can keep spewing this crap and myths about any language and how much he knows. Facts live on.
What makes a language hard?
Lack of skill and practice and time for practice. Some languages take more TIME to learn than others but does that make another language BAD, evil, hard? No. Certain concepts will take more time to learn because it may not exist in another language or it is just difficult for that specific individual. None of this make the LANGUAGE bad, hard or evil.
What makes it hard is the lack of effort, practice and ultimately skill in said language. Wizzup does NOT seem to understand this. It is hard and bad and evil because he said so and he knows all. This is the same argument Linus Torvald had. Except he had more valid points than Wizzup.
He said I'm assaulting him, I'm hurtful, I'm obnoxious, I'm aggressive. No I'm simply stating facts. The LANGUAGE isn't hard.
If you want to say STL is bloated, that's fine but you don't have to use STL; but you lose out on quite a bit unless you roll your own (which by the way you have to do in C anyway). Anything you can do in C, you can do in C++ and more. C++ isn't just object-oriented, it is a multi-paradigm, procedural, function, object-oriented and generic language. C is just procedural and structured.
I'm going to say this once. There is a reason games use C++ and not C. Speed of templates, allocators, and aggressive optimisations by the compiler as well as LESS code. Not to mention the time it takes to write said code.
Now I'm not bashing C because I write C and Assembly all day every day for a living along with Objective-C and Java; I am however saying that it is in no way "SUPERIOR" to any other language out there. Neither is pascal, neither is go-lang.
If you find any language hard, you don't lack the intelligence, you lack practice and time to learn said language.
Right now, I don't care if Wizzup takes offence to this or bans me. I'm already banned from IRC. This egotistical, "I know all" attitude is sickening. I might finally understand what some others that left villavu was talking about.
To say Java is harder than C# is stupid because it isn't. One takes more time and effort than the other but neither is harder than the other. How hard a language is, is simply opinion!
Ban me from IRC and villavu to show off your ego, I don't care. I don't play RS, I code to help other.