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
hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Ravendas posted:

I'm using bcc32 to compile.

Ravendas posted:

What am I doing wrong?

What version of bcc32, exactly? The command-line one that you could download for free? That thing is seriously outdated and you should stop using it ASAP: you will keep stumbling on unimplemented features and bugs, and you will crash it with innocent code sooner or later. Nobody's going to fix its bugs either, since it's a dead product that's since even been sold to a new developer. If that wasn't enough reason for you, keep in mind that the only free debugger that's compatible with it is the text-mode version of Turbo Debugger (td32) and... well, this is what it looks like:



If you have to keep using that compiler, at least don't use its horrifying standard C++ library, use STLPort instead, like Borland themselves did in C++Builder 5

Adbot
ADBOT LOVES YOU

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Ravendas posted:

Things like 'rand not declared in this scope', 'srand not declared in this scope', 'exit was not declared in this scope'...

Do you #include <cstdlib> or #include <stdlib.h>? or you just don't include anything?

If you #include <cstdlib> (<cstring>, <cstdio>, etc.), don't †. Ignore what the books say and #include <stdlib.h> (<string.h>, <stdio.h>, etc.). On the other hand, if you don't include anything and expect the symbols from <stdlib.h> to be defined, you are using a buggy runtime library that pollutes your global namespace by #includeing headers that it shouldn't, and you should re-learn some of your habits

Ravendas, if you need any help in transitioning from bcc32 to a modern environment or in living with that antique, PM me. I have had a sadly long experience with Borland compilers

† So I don't get flayed alive: I know you are supposed to, it's nicer and everything, but don't. #include <stdlib.h> (<string.h>, <stdio.h>, etc.) works in both C and C++ (so no #ifdef __cplusplus #include <cstdio> #else... in library headers) and it's guaranteed to dump the C runtime in the global namespace even in buggy implementations, even the extensions to the standard C runtime that sometimes end up in std:: and sometimes don't. For example: the old Borland <cstdio> puts the _wfopen extension in std::, Microsoft's doesn't: your code that uses std::_tfopen now may or may not work, depending on your compiler and whether it's an Unicode build or not (it's not hard to guess why: some implementations of <cstdio> wrap <stdio.h> in namespace std, some implementations are based on using)

I may be biased about this, though, as I have a long and painful experience writing code that targets multiple toolchains of varying degrees of compliance/brokenness

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Illusive gently caress Man posted:

Why are children responding to Ctrl-C after I close fd 0? Is closing fd 0 the right way to do this? Should I open /dev/null and dup it to 0 instead?

Signals don't come through stdin, you need to detach the children from the controlling terminal, eg. with setsid

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Plorkyeran posted:

Pretty much everything involving reinterpret_cast other than casting a void pointer back to its original type is undefined behavior.

That's static_cast. This is a legal use of reinterpret_cast. As for structure layouts: you cannot portably define the exact memory layout of a structure, but you can ensure your program doesn't compile if your assumptions don't hold: use static_assert with offsetof and is_same to ensure that the offset and type of the two fields is the same. Something like this:

code:
#include <stdio.h>
#include <type_traits>

struct StructA
{
    int a;
    int b;
};

struct StructB
{
    int a;
    int b;
};

static_assert(offsetof(StructA, a) == offsetof(StructB, a), "StructA::a and StructB::a have different offsets");
static_assert(std::is_same<decltype(StructA::a), decltype(StructB::a)>::value, "StructA::a and StructB::a have different types");

int main(int argc, const char **argv)
{
    StructA sa;
    sa.a = 1;
    sa.b = 2;

    printf("%i", reinterpret_cast<StructB*>(&sa)->a);
    return 0;
}
E: might want to ensure StructA and StructB are both PODs, too

hackbunny fucked around with this message at 13:32 on Sep 19, 2013

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

EssOEss posted:

I always thought C++/CLI just enables C++ code to "reach into" the managed world. Are you saying it actually compiles C++ into managed code? Do you have any references to support that? Would love to learn more.

Calls that cross the managed/unmanaged barrier have a huge overhead, so no, C++/CLI compiles directly to CLI in almost all cases. Notable exceptions are:

  • the executable entry point stub, which is Win32 native code
  • functions exported from DLLs, which actually are small native-to-managed stubs
  • likewise, functions imported from DLLs using old-style import libraries instead of P/Invoke are managed-to-native stubs
  • the C and C++ runtime libraries, which are the same native Win32 binaries used by unmanaged C/C++ code

I will never forgive Microsoft for not creating a managed C/C++ runtime based on the BCL, but I guess they always saw C++/CLI as more of a porting/prototyping tool than an actual .NET language

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
I'm embarrassed to be asking this, but...

I have a function that takes an object as a parameter and puts it in a container. To avoid wasting time and memory on useless copies, I declare the argument as a rvalue reference, and std::move() it to the container's insert(). Won't this "steal" a caller's object if it happens to be an lvalue instead of a temporary? How do I avoid this? My guess is an overload that takes a const reference, but I'm not terribly sure. Little help?

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Dicky B posted:

That is the motivation behind std::forward, which preserves the lvalueness/rvalueness of the expression.

rjmccall posted:

You can't convert an l-value to an r-value reference, so the implicit error can't happen. If you want be able to accept either an l-value or an r-value, you have three options. You can make the function take the argument as a value instead of a reference (and then move out of it unconditionally); this requires more formal objects, but as long as move-construction really is cheap, it shouldn't be much of a problem. You can provide a second overload that takes a const &, which means repeating some code but should generate optimal behavior. Finally, you can make the function templated, declare it as taking a T&&, and then std::forward<T> the argument over to the insert function.

Thank you both, I think I get it now, sort of. The point is moot anyway, because I found out I'm limited C++03 :sigh:

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Blotto Skorzany posted:

GCC already gives you warnings for arguments that conflict with the types in printf format strings, no idea what the implementation is based on (probably a bunch of builtin crap)

A bunch of builtin crap, specifically a custom attribute to decorate printf-like functions. It's actually pretty flexible and you can apply it to your own printf-like abominations

Vanadium posted:

Is the problem with iostreams vs stdio really just that overloading << is gross and not the more architectural poo poo?

Have you ever tried to write your own stream subclass?

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

GrumpyDoctor posted:

I'm looking at a codebase that routinely calls function pointers with the wrong number of arguments. It compiles as C, but not as C++. Is there some legitimate reason for this to compile?

As others have said, this is how old school C rocked

I think the closest equivalent of int foo() in C++ would be int foo(...). It's not standards compliant like, at all, but in this particular case I think it's acceptable. Make sure to test it with all possible combinations of argument types, especially pointers, but in this one case where you have one compiler, one platform, one codebase, it's OK. Well, it will work for native code, I'm not sure how managed code will like it...

OK, I tried. It works, both in managed and native mode. This code gives the same output when compiled with or without /clr:

C++ code:
#include <stdio.h>

int aaa(int x, long long y, void *z)
{
	printf("%d %lld %p\n", x, y, z);
	return 1234;
}

static int ccc = 0;

int main(void)
{
	printf("%d\n", aaa(-1000000000, -1000000000000, &ccc));

	int (*bbb)(...) = (int (*)(...))&aaa;
	printf("%d\n", bbb(-1000000000, -1000000000000, &ccc));

	return 0;
}
It's better if you don't see what it compiles to in C++/CLI, though...

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

GrumpyDoctor posted:

C code:
typedef struct {
	char  *funame;			/* function name */
	int  flags;			/* type flags */
#ifdef FUN_ARGLIST
	int  (*funp)(FUN_ARGLIST);	/* pointer to function */
#else
	int  (*funp)();			/* pointer to function */
#endif
}  FUN;
Whatever you want to argue about where that falls on the clever-horror scale, FUN_ARGLIST is never defined anywhere, and they just rely on this behavior of argumentless function pointers to make everything work. (And this particular struct isn't the only place this comes up.)

C code:
#define FUN_ARGLIST ...
You'll have to add a cast everywhere funp is assigned. You can't really replace the naked function pointer type with a wrapper class that does the cast for you, because that requires variadic templates, which the Microsoft compiler doesn't support

I will not in any way pretend this isn't terrible, but in your specific combination of compiler and environment it will work

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

OK, I found the library you're using, and you don't need variadic templates, all the functions have between one and two arguments. Also the code is very polite and dereferences function pointers before calling them, so you don't even need operator(). Add this to otypes.h, before FUN:
C++ code:
struct ofunp
{
private:
    int (* m_pfun)(...);

public:
    template<class ArgT>
    const ofunp& operator=(int (* pfun)(ArgT))
    {
        m_pfun = (int (*)(...))pfun;
        return *this;
    }

    template<class Arg1T, class Arg2T>
    const ofunp& operator=(int (* pfun)(Arg1T, Arg2T))
    {
        m_pfun = (int (*)(...))pfun;
        return *this;
    }

    auto operator*() const -> decltype(*m_pfun)
    {
        return *m_pfun;
    }
};
and then change the definition of FUN to:
C++ code:
typedef struct {
        char  *funame;                  /* function name */
        int  flags;                     /* type flags */
        ofunp funp;                     /* pointer to function */
}  FUN;
It won't be terribly efficient though, variadic calls go through native code

Have you tried compiling the library as a native static library, and then linking to it?

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

GrumpyDoctor posted:

Another question: Why does this
C code:
#ifdef _WIN32
extern double	erf(double x);
extern double	erfc(double x);
#endif
emit an "inconsistent dll linkage" warning for each declaration? I'm compiling as a static library.

Are you getting this warning when you compile the library, or when you compile your C++/CLI application? because if it's the latter, you probably do need to wrap the library's headers with extern "C" {}

But yes, post the exact error

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

GrumpyDoctor posted:

code:
warning C4273: 'erf' : inconsistent dll linkage
The file is located in a header, and the warning is emitted each time it's included in a .c file. This happens just when the static lib is compiled (that suggestion worked great), so no C++ or managed code is involved yet.

What version of Visual C++ are you using? Mine only supports erf and erfc when compiling GPU code, yours could have them in the libc too. In that case they will be declared in <math.h> as _CRTIMP, which will expand to __declspec(dllimport) when compiling with /MD, which will conflict with Radiance's redeclaration as extern

OK, from the documentation it seems erf/erfc were added to Visual Studio 2013. You need to get the compiler's version, just run cl from the command line, you'll get output like this:
pre:
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]
See the version number, in MM.mm.bbbbb format? note it down as MMmm (1700 in my example), then change the #ifdef _WIN32 around erf and erfc to #if defined(_MSC_VER) && _MSC_VER < version in MMmm format. This will prevent redefinition of erf and erfc when using a version of the Microsoft compiler that implements them, in a way that you can submit upstream

e: of course, exclude Radiance's implementation of erf and erfc from the build of the static library

GrumpyDoctor posted:

And another question: Can I use __declspec(thread) in this static library that is linked into a C++/CLI mixed-mode assembly? Implicit TLS didn't use to work in .DLLs not present at process start, but I don't know if that restriction applied to managed assemblies, or if it's still around.

It's supported in Vista and later. If you need to support Windows XP, you can always turn the variable into a getter/setter pair I guess

hackbunny fucked around with this message at 13:15 on Nov 15, 2014

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Risket posted:

I'm using Visual Studio 2010, and the program will be run on Windows 7 and maybe 8 using the command prompt.

If you run a GUI program from the command prompt, the command prompt will not wait for it to terminate. If it's important that the command prompt knows when your program terminates (for example if it has to be called from a batch script), then compile it as a console application. Yes, console applications can create windows

Risket posted:

__argv works in my testing, but I keep reading that I shouldn't use __argv but I having trouble finding out why.

It's non-standard as you can tell from the double underscore, but who cares. Me, I would use wmain (int wmain(int argc, wchar_t **argv)), and then manually set the program as a GUI program in the linker settings (look in the project's settings, look for "subsystem" under linker settings), but WinMain with __argc and __argv is perfectly fine. Not sure if you really need getopt/Boost.ProgramOptions, depends on how complex your command line arguments are

Risket posted:

Also, should I be using ASCII or Unicode? Does it matter?

Use Unicode. I don't know if it matters to your particular application, but Unicode is pretty much standard everywhere nowadays

If you need to interact with third party Unicode libraries, Windows Unicode strings are in UTF-16 format and need to be converted if you need UTF-8

Risket posted:

Edit: I should have said, Visual Studio generated the program entrance as:
code:
 int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)

All arguments to WinMain are data you can get from GetModuleHandle, GetStartupInfo or GetCommandLine. There's nothing magic to them, and the WinMain parameters are only kept for backwards compatibility with 16 bit Windows (where hPrevInstance could be something other than NULL for example), so don't read too much into them

Risket posted:

I guess what Im asking is what would be the best way to capture the command Iine arguments and aprse them from there.

Get them with argc/argv or __argc/__argv, parse them however you like

I wouldn't use CommandLineToArgvW because it uselessly duplicates work the C/C++ runtime library already does

roomforthetuna posted:

Aren't the W versions of functions a horrible kind of Unicode?

UTF-16, it's alright

roomforthetuna posted:

Is there no UTF-8 for Windows GUI stuff?

No and it's a little silly, but that's how it is

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

pseudorandom name posted:

hackbunny had a good explanation as to why Valgrind will never happen on Windows in the YOSPOS thread.

Unless Microsoft gets involved directly, which I had never considered. Microsoft has done weirder things recently, so, why not

pseudorandom name posted:

in the YOSPOS thread.

IIRC it wasn't in the thread but linked from the OP

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

zergstain posted:

After a while of Googling, I haven't been able to get a clear answer on whether QPC() measures CPU time or actual time. I need an operation to occur every 100ms, so I need actual time. If not QPC(), what should I use?

I'm stuck in MFC or WINAPI land. I posted this in the .NET megathread, but someone suggested posting here. Thought this thread was more for language questions and less for specific APIs/frameworks.

I don't want to type the actual function name on my phone.

It's complicated and depends both on the hardware and the Windows version

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Schmerm posted:

Each time I register a class, I want to scan through all the already-registered classes and see if the incoming class is a subclass of any of them, and use that information to update the ordering/relationship of the registered classes.

It seems incredibly silly to me, but std::type_info (what I would have used) does not support this

e: not with the standard std::type_info at least, of loving course this information is available to the runtime environment for exception handling

e2: do you have any code to show us?

hackbunny fucked around with this message at 01:09 on Jan 16, 2015

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

sarehu posted:

So far what it seems to me is that packing has nothing to do with it. It'll return in al/ax/eax if the size is 1, 2, or 4 (I don't know if eax should be zero extended for the smaller values or not) and eax:edx if the size is 8. Otherwise you have a return pointer parameter passed on the stack and its value, the pointer to the struct, is returned in eax. This is true even if the struct of size 8 is packed to alignment 1 and has a short at offset 3 -- eax gets one of its bytes and edx gets the other.

I have no idea if a callee that takes a return pointer might possibly return a different value in eax that points at a different struct.

Also a struct with just a double in it will go in eax:edx, unlike a return value of type double, which goes in a floating point register.

What do you need to know about cdecl on x86 and what for?

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

roomforthetuna posted:

Evidently the answer to this is "not that one anyway".
code:
int main() {
 linear_congruential_engine<unsigned int, 48271, 0, 2147483647> gen(12345);
 uniform_int_distribution<int> dist(0,9);
 for (int i = 0; i < 20; ++i) {
  cout << dist(gen) << endl;
 }
}
On windows from Visual C++ the numbers consistently begin 4, 1, 5. On linux from g++ the numbers consistently begin 2, 7, 6.

I think the difference is in the implementation of uniform_int_distribution, linear_congruential_engine is a well-known algorithm

e: the first outputs of gen in your example should be 595905495, 1321844800, 1593306094

hackbunny fucked around with this message at 05:52 on Mar 1, 2015

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

jon joe posted:

I'm not sure I entirely understand std::function. I googled for some more information and am still confused. Could anyone please explain it simply to me?

Generalized pointer to function, because while in C there is just one type of thing that you can "call", in C++ there are tons: stand-alone functions, member functions, lambda expressions, any objects that overload operator(). std::function lets you call anything that can be considered callable, as long as you pass the right arguments, hiding the details of what exactly you're calling. It's not perfect: it's polymorphic which adds an extra indirection, and it doesn't support overloaded functions (or does it?), but it beats any alternative

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Sex Bumbo posted:

It supports overloaded functions, you just have to cast the function.

I meant implementing an overload of operator() for each overload of the input function, but that's both impossible in the current language I guess, and against std::function's nature as a C++ replacement for C function pointers (a "pointer" can only point to one thing). In fact what I said didn't make a lot of sense

The Laplace Demon posted:

std::function, while magical

I don't think it's magical, it's a standardization of boost::function. I've looked inside boost::function before and it's simpler than you may think

hackbunny fucked around with this message at 21:45 on May 20, 2015

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
It's not, it's specialized as an array of bits. Bits are not addressable in C++, and the big thing about vector is that it's a type-safe and bounds-checked replacement of a variable-sized C array, with contiguous, addressable elements, compatible with pointer arithmetics on element addresses etc. (although this wasn't actually documented in the standard until recently). Everywhere you take a vector<T> you either have to code defensively and only use iterators, or specialize for vector<bool> and its limitations

It's basically an entire different class that's similar but not the same as vector

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Jinx posted:

What happens when a 32-bit userspace binary makes a syscall on a 64-bit Linux kernel? I'm fairly ignorant; I assume that the kernel knows it's handling a 32-bit binary and has special magic to deal with the fact that there are 64-bit registers, right? I can't seem to find any documentation about this topic, however it could be that I simply do not know what to look for.

I don't know about Linux and x64 specifically, but system calls are typically implemented like this:
  • user mode prepares arguments for the system call on the stack or in registers
  • user mode executes a special system call instruction instead of a regular call instruction
  • the processor switches to kernel mode, saves just enough information on the kernel mode stack to return to user mode after the system call instruction, and calls the system call dispatcher
  • the system call dispatcher saves the registers, typically on the stack in a structure called "trap frame"
  • the system call dispatcher determines the system call number from the saved registers, and based on the system call number copies the system call arguments to kernel memory, and calls the appropriate handler
  • the handler does what user mode asked, and returns to the system call dispatcher
  • the system call dispatcher overwrites the saved value of the return value register with the value returned by the handler (this is typically a status code)
  • the system call dispatcher returns to user mode

The system call dispatcher can tell a 32-bit and a 64-bit apart in many ways: either they enter kernel mode with a different instruction (therefore a different dispatcher), or some of the information saved by the processor during the user-kernel switch can be used to tell them apart

Jinx posted:

Perhaps let me be more specific - what *should* happen when the syscall API uses a structure (hidden behind a void* of course) that has different alignment in 32-bit and 64-bit binaries?

Different alignment alone isn't an issue because it's good practice to copy indirect arguments to kernel memory before using them: since the kernel will be compiled as 64-bit code, the structure variable you use as a temporary buffer will have the correct alignment. In fact, I think in Linux you plain can't access the user mode address space from kernel mode

Jinx posted:

Who should deal with an offset discrepancy with one of the fields in the structure - user or kernel space?

Depends on the operating system, I don't know what's the common practice on Linux. Windows AFAIK uses a translation layer in user mode: a 32 bit "system call" actually switches the processor to 64 bit, but stays in user mode, where an intermediate system call dispatcher/handler translates structures to their 64 bit format, and then performs the actual system call (with some exceptions, for example in asynchronous I/O calls: asynchronous results are reported by the kernel directly writing to an user-allocated structure composed of pointer-sized fields, which obviously has different sizes in 32 bit vs 64 bit code, so each asynchronous request has to know if it was submitted by a 32 bit or a 64 bit process)

I can look into the Linux sources and see if I can tell you more

... although I have to wonder if you are embedding pointers in a structure passed to kernel mode. That would be a bad idea. If you aren't, you should have the same field offsets if you use types that have the same size/alignment in 32 bit vs 64 bit (e.g. not long)

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Xarn posted:

Can someone explain that to someone lucky enough to get started with git as source control?

CVS is a positively ancient revision control system. How bad is it, really? Revision numbers are per-file, forget atomic commits. Forget history-preserving moves and copies in fact. Good luck bisecting, without atomic commits you have to work with loving timestamps. Good loving luck branching and merging. Can't even delete directories, the client has an option to automatically clean up empty directories. Advantages (or: how worse could it have been?): unlike its predecessor, RCS, it's client-server

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Slash posted:

How about the STL?

All implementations I've seen have unreadable code. Not necessarily bad code, they're just coded very defensively and to very strict specifications. See how all the internal identifiers and class names are ugly underscore salads so that they are virtually guaranteed not to conflict with macros defined by the user or other libraries; or how comparisons are strictly performed with the < operator because it's the only ordering operator required to exist (yeah I know about less<T>, I know I'm simplifying). Plus all the template parameters that most data structures have that aren't strictly related to the data structure/algorithm (e.g. allocator parameters), or that are a level of abstraction too far for just learning about data structures (e.g. ordering predicate parameter). In some implementations, several containers are even based on a shared implementation (in STLport, if I'm not mistaken, the same RB-tree is used to implement map<> and set<>), written in horrible C/non-templated C++. Not to mention that most of its code is written for performance, not clarity

It's a great learning experience on how to write robust C++ libraries, on how to improve code performance by using function overloading, template specialization and other tricks, but for learning about data structures and algorithms, ugh

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

xgalaxy posted:

- I wouldn't have templates (I'd use generics)

Aaand you lost me

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Sex Bumbo posted:

Why should I be excited for concepts? It seems like a lot of code for the same result.

Because tag-based dispatch is awful

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

OneEightHundred posted:

1.) MSVC ignores the missing ";" syntax error unless it has to instantiate the function. :lol:

Oh, yeah, in MSVC templates are implemented much like macros, with token substitution (they say they are working on it). Don't forget to parenthesize references to expression parameters!

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

OneEightHundred posted:

... what happens if you don't do this?

Same thing that happens when you don't parenthesize macro arguments. This was back in 2003 I think, I wonder if it has been fixed in the meanwhile

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Dessert Rose posted:

I've heard good things about Qt but I've never actually done any work in it myself. It's probably better to learn Qt than MFC though.

It's good! really good! Can't really comment on the graphics/UI part because I'm using it on a platform (BlackBerry Native) which has its own UI framework (Cascades) specifically incompatible with Qt's standard UI, but the whole QObject framework is very powerful and its message-passing makes multithreading and structuring your application into independent components painless. Its various container/data classes are pretty good too, as they're all based on shared copy-on-write storage and they can be copied in O(1) time (very important in pre-rvalue reference C++); the containers are STL-compliant too. Yes, it has its own project file format and several mandatory non-standard build tools, and I never used it in Visual Studio, so I can't comment on how well it integrates with it, but code-wise it's a solid choice

MFC is the best choice for Windows and has the best integration with Visual Studio (Visual Studio and MFC are virtually designed for each other), but it's Windows-only

hackbunny fucked around with this message at 14:29 on Nov 7, 2015

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
I don't have the standard handy, but I think it's safe. I know there are linker optimizations to fold identical constants to save space in the executable, which cause distinct static objects to have the same address, but it seems that in Visual C++, for one, you have to explicitly request it when you declare the variable

Function pointers don't have the same guarantee IIRC, but again, I don't have the standard handy to check

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Sex Bumbo posted:

If you load a DLL I'm pretty sure they won't agree on type ids. Maybe that's not important though.

Oh, ick, you're right. You'd be forced to explicitly instantiate the template for classes exported by the DLL, and export the explicit instantiation as well. In fact I think this is exactly what Qt does

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
Holy poo poo don't use placement new, ever. You need a drat good reason to use placement new

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

nielsm posted:

To elaborate: On Windows, you'll have to use the WaitForSingleObject() function.

No, Windows has no equivalent of select/poll/epoll/kpoll, period. Windows asynchronous I/O follows the aio model, scratch that, Windows asynchronous I/O is aio after a search-replace: OVERLAPPED is struct aiocb, GetOverlappedResult is aio_suspend/aio_return, CancelIoEx is aio_cancel

Use a library/framework that hides all the complexity of asynchronous I/O or you'll go insane. There is no portable way to do it efficiently, and in some combinations of platform/device/operations you will have to spin a thread (Windows console I/O is a big one) or use non-standard operations (for example WaitForSingleObject on a console input handle works like select instead of working like aio_suspend, like it does for all other file handles)

I can't recommend any in particular, though, but never ever ever write low level async I/O code

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
I can personally vouch for Qt. It's a really good framework. It does complicate your build slightly, because you need to run an extra tool (moc, Meta Object Compiler) to enable all features relying on type metadata, but QObject and the signals/slots system are really good. Some parts of Qt have been obsoleted by recent changes to the language, but it's still good, and it's always been a pleasure to work with in my experience

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Ralith posted:

Doesn't goto also skip destructors that would otherwise be called when control leaves a given block? That could cause all kinds of trouble, especially if you use RAII much.

goto (and switch) can skip constructors, but that's a compilation error. Nothing can skip destructors! that would seriously compromise the integrity of a program

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
I should have added an asterisk to that "nothing". Placement new is another easy way to skip destructors (I don't recommend using placement new, like ever)

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

roomforthetuna posted:

Why is placement new special for skipping destructors? You can skip destructors with any 'new' you like, by not calling delete, just like you might skip calling the destructor with placement new.
Do you mean that you have to explicitly specify how to call the destructor if you're unique_ptr-ing a placement new?

No placement delete, you have to call the destructor (!) yourself. Don't use placement new unless you're absolutely totally sure of what you're doing

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Ciaphas posted:

Is fopen not supposed to fail if you try to open for writing a file that's already open for writing by another process?

It's OS-dependent. It will fail on Windows and succeed pretty much everywhere else

Ciaphas posted:

(edit) It appears fcntl() is what I need to go look up and learn how to use, especially advisory locks

... which, on the other hand, Windows doesn't implement. But I guess it's not an issue for you

Adbot
ADBOT LOVES YOU

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Ciaphas posted:

Nope, long as it works on Solaris and Linux (it did) I'm good.

Handy that posix locks seem to work over NFS, too.

Word of warning, advisory locks don't work too good on NFS. I don't know the details but it's one of the well known weak points of the protocol

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