Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411428 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 19, 2024, 02:33:51 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)What's your favorite programming language?
Pages: 1 ... 8 9 [10] 11 12
Print
Author Topic: What's your favorite programming language?  (Read 21322 times)
tjcbs
Level 1
*


View Profile WWW
« Reply #180 on: October 20, 2014, 02:58:33 PM »

Personally I think the preprocessor is what's holding back C++.  Template expansions, references to external functions, and private members (for struct sizing) should be resolved at link time, not compile time.

It often does, with compilers that support global optimization. But why do you care? How is it holding back c++?
Logged

Sik
Level 10
*****


View Profile WWW
« Reply #181 on: October 20, 2014, 10:01:20 PM »

While I keep seeing people saying the preprocessor is evil... I really would like to know how would you handle stuff like this at compile time:

Code:
#ifdef _WIN32
   // Stuff using Windows API
#else
   // Stuff using POSIX API
#endif

Some people insist that you should be using if instead, but how do you prevent the errors that arise from the involved functions and values not existing? =P (and using separate files is not really that feasible when it's only a small chunk of code that needs to be platform-specific)
Logged
Boreal
Level 6
*


Reinventing the wheel


View Profile
« Reply #182 on: October 20, 2014, 11:04:01 PM »

Not saying it should be gone, there are plenty of areas where having the preprocessor does help compile times and make things easier.  But at the moment we're forced to choose between compile time and run time, with no option to make things happen at link time.
Logged

"In software, the only numbers of significance are 0, 1, and N." - Josh Barczak

magma - Reconstructed Mantle API
Geti
Level 10
*****



View Profile WWW
« Reply #183 on: October 20, 2014, 11:58:17 PM »

@Sik: "ideally" link against something (in-house or otherwise (SDL)) that abstracts away those platform-specific APIs. We have way too much of that fragile, #ifdef-reliant platform-specific code scattered through KAG and its a pain in the arse debugging it when something goes wrong and keeping code in sync across platforms when something changes. It's a fragile way to write code that shouldn't really be present at the application/game level.

The weird middle ground that a lot of us get stuck in where >99%+ of the code is platform independent, so the rest being wrapped in preprocessor splits isn't enough of a pain to remove is pretty toxic.

Write against libraries that work the same on your target platforms, or else write platform-specific.

Extra bad points in KAG source where we've got defines for WIN32, UNIX, LINUX and OSX (the latter 2 for where linux and osx differ in the fine-print)
Logged

Sik
Level 10
*****


View Profile WWW
« Reply #184 on: October 21, 2014, 09:22:25 AM »

And then what do we do with the code of those portable libraries? Because under the hood they're dealing with exactly the same issues =P
Logged
Layl
Level 3
***

professional jerkface


View Profile WWW
« Reply #185 on: October 21, 2014, 09:29:14 AM »

And then what do we do with the code of those portable libraries? Because under the hood they're dealing with exactly the same issues =P

The code inside those libraries probably uses an external "Platform" object, one for each platform.
Logged
Boreal
Level 6
*


Reinventing the wheel


View Profile
« Reply #186 on: October 21, 2014, 01:55:08 PM »

What I do in terms of cross-platform support is changing back ends at link time.  So if I was (for example) implementing the entry point, I would have files like entry_win32.cpp, entry_x.cpp, entry_cocoa.cpp, and so on, each implementing the same concept but with different platforms.

In terms of building, I leverage CMake to make it simple.  In each subsystem that requires multiple implementations, the platform-specific source goes in its own subdirectory.  So for the video system, there would be video/d3d, video/gl, etc.  Each subdirectory would have its own CMakeLists.txt script.  Then there is a top-level CMakeLists.txt script in video that chooses which subdirectory to enter.

Code:
if(WIN32)
    add_subdirectory(d3d)
else
    add_subdirectory(gl)
endif(WIN32)
Logged

"In software, the only numbers of significance are 0, 1, and N." - Josh Barczak

magma - Reconstructed Mantle API
Geti
Level 10
*****



View Profile WWW
« Reply #187 on: October 21, 2014, 04:56:36 PM »

And then what do we do with the code of those portable libraries? Because under the hood they're dealing with exactly the same issues =P
You write them in C, where there's still the preprocessor Smiley
Logged

Sik
Level 10
*****


View Profile WWW
« Reply #188 on: October 21, 2014, 11:20:58 PM »

And then you defeat the whole point of getting rid of it in the first place. Ideally the language should be good enough that you don't have to resort to other languages at all (except when interfacing with this written in other languages or possibly raw hardware access, nothing else).

EDIT: of course, there's the question of why the standard library of the language doesn't abstract all that in the first place.
Logged
Geti
Level 10
*****



View Profile WWW
« Reply #189 on: October 22, 2014, 01:54:57 AM »

The joke is that "ideal" and "programming language" are in the same place at the same time, haha. Indeed, ideally the standard library would actually cover all the boilerplate crap that you need.

Unfortunately, in C++ you essentially are resorting to another language when you're writing preprocessor statements.

Re: writing the portable libraries without #ifdefs - one can of course split the modules as necessary at a file level (as you alluded to, and boreal elaborated on), and modify one's include path to include different files on different platform wrapping the needed API - the main point is that you end up with a library with the same symbols that provide the same semantics regardless of the platform; this doesn't require the preprocessor.

My view when considering the #ifdef PLATFORM #elseif OTHERPLATFORM #else #endif garbage "evil" is that it really shouldn't be in your application-level code at all; it's fragile, hard to read for nontrivial blocks of code, and can quite easily lead to a subtle warping of the semantics of your code on each platform.
Logged

jgrams
Level 3
***



View Profile
« Reply #190 on: October 22, 2014, 06:42:28 AM »

My view when considering the #ifdef PLATFORM #elseif OTHERPLATFORM #else #endif garbage "evil" is that it really shouldn't be in your application-level code at all; it's fragile, hard to read for nontrivial blocks of code, and can quite easily lead to a subtle warping of the semantics of your code on each platform.

Yeah. I think that if you push it down to a low level, you can usually deal with only one or two parameters changing. e.g. maybe the low-level module only cares about and deals with different newline character sequences, so it's simple and clear to understand what changes.

But if you just throw #ifdefs willy-nilly in your application-level code they can wind up affecting all kinds of things at once. So #ifdef WINDOWS might mean CRLF line endings, and backslashes for directory separators, and storing game config info in the registry, and, and, and...) and that's what ends up being a maintenance nightmare. If you handle the porting so that each individual choice only matters for one small module in the code, and everything else uses the consistent interface provided by that module, that sort of #ifdef seems to be pretty easy to manage.

Jarzabek, Xue, Zhang, and Lee's 2009 paper Avoiding Some Common Preprocessing Pitfalls with Feature Queries has some interesting things to say about the problem in general.

Edit: Oh, sorry. I've got the conversation turned around. @Sik: the two people I've known who went around telling everyone that the C preprocesser was the work of the devil were both hotheads who had a job in their past where they had to work on a project with major tangles of nested #ifdefs. Other than that I've only known people who have heard it from others, or who think that it's easily abused and you have to be careful with it (like Geti, if I'm reading that last post correctly).
« Last Edit: October 22, 2014, 08:03:26 AM by jgrams » Logged
Geti
Level 10
*****



View Profile WWW
« Reply #191 on: October 22, 2014, 01:22:49 PM »

I'm a bit of the first and the last Wink I've been working in a big codebase with far too much preprocessor code for years, but I've been writing a fair bit of C recently where it's more commonly used in less evil ways Smiley I still prefer #pragma once to include guards though.
Logged

Boreal
Level 6
*


Reinventing the wheel


View Profile
« Reply #192 on: October 22, 2014, 07:09:11 PM »

This is why I love C.

Code:
switch(mode)
{
    case(0): if(test(a, b))
             {
    case(1):     result = foo(a, b);
                 break;
             }
             else
             {
    case(2):     result = bar(a, b);
                 break;
             }
}

Just let that sink in for a bit.
« Last Edit: October 22, 2014, 07:14:57 PM by Boreal » Logged

"In software, the only numbers of significance are 0, 1, and N." - Josh Barczak

magma - Reconstructed Mantle API
InfiniteStateMachine
Level 10
*****



View Profile
« Reply #193 on: October 22, 2014, 08:17:58 PM »

yikes
Logged

SolarLune
Level 10
*****


It's been eons


View Profile WWW
« Reply #194 on: October 22, 2014, 09:02:37 PM »

I have no opinion on anything, just... I know all of the elements in that chunk of code, but I can't read it. It's like you threw Python into the middle of C.
Logged

dancing_dead
Level 2
**


View Profile
« Reply #195 on: October 22, 2014, 09:22:50 PM »

This is why I love C.

Code:
switch(mode)
{
    case(0): if(test(a, b))
             {
    case(1):     result = foo(a, b);
                 break;
             }
             else
             {
    case(2):     result = bar(a, b);
                 break;
             }
}

Just let that sink in for a bit.

that actually works? Shocked
Logged
Geti
Level 10
*****



View Profile WWW
« Reply #196 on: October 22, 2014, 11:28:16 PM »

@Boreal - perhaps more readable? certainly terser Wink

Code:
result = (!mode && test(a,b) || mode == 1) ? foo(a,b) : bar(a,b);
Logged

Sik
Level 10
*****


View Profile WWW
« Reply #197 on: October 23, 2014, 02:49:40 AM »

Unfortunately, in C++ you essentially are resorting to another language when you're writing preprocessor statements.

OK yeah, it'd be nicer if this stuff was part of the language itself =P

My view when considering the #ifdef PLATFORM #elseif OTHERPLATFORM #else #endif garbage "evil" is that it really shouldn't be in your application-level code at all; it's fragile, hard to read for nontrivial blocks of code, and can quite easily lead to a subtle warping of the semantics of your code on each platform.

I guess, the problem is when the libraries aren't helping you. E.g. in my game I use both SDL2 and PhysicsFS, and indeed the code is portable for the most part, but there are a few things (related to file paths, more specifically) where it still falls short. For example, I wanted a way to retrieve the pictures directory (said concept existing on both platforms I'm working on, and even when not I'd be happy with a fallback). Neither library provides a way to retrieve that path, so I had to write platform-specific code just for it (yes, it's wrapped into its own function so nothing else has to worry about it), and it wouldn't make much sense to make separate files just for a single 33 lines function (comments and blank lines included) when every other file function was in the same file.

Ideally it'd be nice if the libraries included those functions (probably PhysicsFS, although SDL2 now has functions for retrieving some paths), but until then one has to cope with what's available =P

that actually works? Shocked

Yeah, the case statements are internally just labels (and as such fall under all the same restrictions as you'd have with goto - heck, you can use goto with them). Same thing works in C++ too.
Logged
Geti
Level 10
*****



View Profile WWW
« Reply #198 on: October 23, 2014, 03:27:19 AM »

Of course, but in that case wouldn't mind the #ifdefs.
That kind of code ("get the pictures folder on this platform, or a fallback inside appdata or whatever") is kind of on the border between application and engine/backend/core/whatever, but I'd say more towards the latter - it's going in with your file operations, which are also generally reasonably low level.

I'd potentially consider splitting out your file operations to an internal (static) lib to be maintained over time and reused between projects, though a header and implementation file is of course ok too.

...This is quite the tangent, haha Smiley
Logged

Rusk
Level 1
*


View Profile
« Reply #199 on: October 23, 2014, 04:23:22 AM »

This is why I love C.

Code:
switch(mode)
{
    case(0): if(test(a, b))
             {
    case(1):     result = foo(a, b);
                 break;
             }
             else
             {
    case(2):     result = bar(a, b);
                 break;
             }
}

Just let that sink in for a bit.

That's cool. Suddenly the switch statement makes sense, rather than being just some awkward syntax to be memorized. Thanks!
Logged
Pages: 1 ... 8 9 [10] 11 12
Print
Jump to:  

Theme orange-lt created by panic