Tag Info

Hot answers tagged

46

Besides the void * pointer which is covered in Robert's answer, a technique like this was used (Disclaimer: 20 year old memory): #define WANTIMP #define TYPE int #include "collection.h" #undef TYPE #define TYPE string #include "collection.h" #undef TYPE int main() { Collection_int lstInt; Collection_string lstString; } Where I have forgotten ...


43

The traditional way to implement generics without having generics (the reason templates were created) is to use a void pointer. typedef struct Item{ void* data; } Item; typedef struct Node{ Item Item; struct Node* next; struct Node* previous; } Node; In this example code, a binary tree or doubly-linked list can be represented. ...


42

You should always include all headers defining any objects used in a .cpp file in that file regardless of what you know about what's in those files. You should have include guards in all header files to make sure that including headers multiple times does not matter. The reasons: This makes it clear to developers who read the source exactly what the ...


22

No, not every function is a closure. Wikipedia says: ... closure ... is a function or reference to a function together with a referencing environment — a table storing a reference to each of the non-local variables (also called free variables or upvalues) of that function. I'd add "non-local and non-global", but the idea is correct. Neither your ...


15

As other answers pointed out, you can use void* for generic data structures. For other kinds of parametric polymorphism, preprocessor macros were used if something got repeated a lot (like dozens of times). To be honest, though, most of the time for moderate repetition, people just copied and pasted, then changed the types, because there are a lot of ...


14

The general rule of thumb is: include what you use. If you use an object directly, then include its header file directly. If you use an object A that uses B but do not use B yourself, only include A.h. Also while we are on the topic, you should only include other header files in your header file if you actually need it in the header. If you only need it in ...


9

This really is a matter of opinion, but for what it's worth, I find it misleading to return the modified item if the item is modified in place. Separately, if predictPrice is going to modify the item, it should have a name that indicates it's going to do that (like setPredictPrice or some such). I would prefer (in order) That predictPrice was a method of ...


9

The pure fact you don't understand this function should be a big warning sign not to implement your Tic-Tac-Toe winning test in a similar manner. If you do, you will probably not understand your own code in a few weeks any more. Instead, use a two-dimensional array or vector, and some loops to check the winning conditions. And don't think too much about ...


8

I remember when gcc shipped with genclass - a program which took as input a set of parameter types (e.g. key and value for a Map) and a special syntax file which described a parameterized type (say, a Map or a Vector) and generated a valid C++ implementations with the param types filled in. So if you needed Map<int, string> and Map<string, ...


7

I keep wondering whether or not I should explicitly include all headers used directly in a particular file Yes. You never know when those other headers might change. It makes all the sense in the world to include, in each translation unit, the headers you know that translation unit needs. We have header guards to ensure that double-inclusion is not ...


7

[To the OP: I'm not trying to pick on you personally, but raise your and others' awareness of thinking about the logic of the question(s) asked on SE and elsewhere. Please don't take this personally!] The title of the question is good, but you are severely limiting the scope of your answers by including '... situations where they needed compile-time code ...


6

Uniform initialization syntax seems geared to aggregate types. Looking at the FAQ, UIS's purpose is to solve a variety of loosely (or subtly?) related problems (ambiguities and impossibilities), some of which don't exist or have other solutions in other languages. Consequently, I don't think you'll find anything exactly the same in other languages; you may ...


6

When you split up big methods into smaller ones, and separate concerns to many classes, and write more functions with clearly separated levels of abstraction, you will end up with long call chains, that's true. But when you choose your abstractions well your code becomes much more readable and understandable than the typical 200 lines-of-code-spagetthi ...


6

So I think you're working from a false premise. I believe you assume that if there are non-zero values in the memory space that was just allocated that the memory was somehow not properly allocated. And that's a horrific assumption that's going to burn you badly later on as you build more complex programs. Suffice it to say that the memory is being ...


6

Sometimes it's appropriate to add constructor to a struct and sometimes it is not. Adding constructor (any constructor) to a struct prevents using aggregate initializer on it. So if you add a default constructor, you'll also have to define non-default constructor initializing the values. But if you want to ensure that you always initialize all members, it ...


5

If you don't use virtual functions, then there should be no (negative) performance or space impact on using C++ classes when comparing to C structs. The two snippets you gave as example should compile to (nearly) the same assembly code.1 If you add virtual functions to your classes, then there will be a slight memory overhead per object (about the size of a ...


5

This is very much a judgement call, but I would agree with you that explicit values are the way to go, plus a comment at the start explaining the significance of the explicit values. As an example of a prominent project that is doing it this way, look at Clang's AST serialization. It uses a huge enum to define codes for all of its AST nodes, and the enum ...


5

In Jenkins you can setup different build slaves (which could run on different physical or virtual machines). Your Jenkins master could then delegate different build jobs to the corresponding slave (also in parallel). So in your case you could setup some Jenkins slaves where every slave runs on a virtual machine with a different operating system. Your ...


5

C# has something similar; they're called Object/Collection Initializers. They have several, but similar, forms: // Object initialization var cat = new Cat { Age = 10, Name = "Fluffy" }; // Object initialization with anonymous type var pet = new { Age = 10, Name = "Fluffy" }; // Collection initialization var digits = new List<int> { 0, 1, 2, 3, 4, ...


5

Within an object oriented design paradigm, things shouldn't be modifying objects outside of the object itself. Any changes to the state of an object should be done through methods on the object. Thus, void predictPrice(Item item) as a member function of some other class is wrong. Could have been acceptable in the days of C, but for Java and C++, the ...


5

The answer is yes. The Linux kernel is written almost entirely in C. A very teeny-tiny portion is written in assembler, and those portions consist of only portions related to low-level functions that can't be done in C, such as setup of the target CPU at boot, setting up hardware interrupts, power information through ACPI/EFI, etc. Otherwise, pretty ...


5

Horrible macros is right, from http://www.artima.com/intv/modern2.html: Bjarne Stroustrup: Yes. When you say, "template type T," that is really the old mathematical, "for all T." That's the way it's considered. My very first paper on "C with Classes" (that evolved into C++) from 1981 mentioned parameterized types. There, I got the problem right, but I ...


5

That depends on how you plan to recover from these exception, meaning what code is executed in the catch statements. If it's the same for all 3 exceptions, you could create a superclass for them and catch the superclass. If your method has to throw a new exception, just make it extend the superclass and it would still be caught by the caller and would not ...


5

Because the c_str() doesn't prevent the string from being cleaned up. After the function returns and bar is cleaned up then the foo strings are also cleaned up which may be before the thread starts. You should pass the actual std::string (possibly to a wrapper that then extract the char* before calling func) or otherwise ensure the strings don't get cleaned ...


5

The core issue with threading here is that the parent thread will do stuff with the memory at the other end of those pointers, making them invalid. What you need to do is pass std::string into each thread. Not a reference, not a pointer, but a copy. Now each thread owns its own copy of the string, which will be automatically cleaned up via the magic of the ...


4

As Robert Harvey already said, a void pointer is the generic data type. An example from the standard C library, how to sort an array of double with a generic sort: double *array = ...; int size = ...; qsort (array, size, sizeof (double), compare_doubles); Where compare_double is defined as: int compare_doubles (const void *a, const void *b) { ...


4

Closures are an efficient way to implement functions. I claim that every function is conceptually a closure, even in the few languages which don't have them. The closed variables are then constants or static data inside the code. But in full-fledged closures (like in Ocaml, Scheme, Common Lisp, or C++11) the closed variables and the code are in the closure ...


3

If you want to determine the relative or absolute errors for a computation which is too complex to be estimated manually, you could try using interval arithmetic. This approach will help you to trace the error in each of your variables throughout the calculation process. Of course, you will typically have to implement something like Gauss elimination by ...


3

Importing in Java, C# and the like is fundamentally different from including in C and C++: The former will add the named modules to those considered for symbol resolution, the latter inserts the named headers content literally into the translation unit. Which means a header can contain anything the source-file can, including translation-unit-local objects ...


3

Let's think about this very carefully. libA.so is statically linked with the STL. However, the STL does not exist in isolation, it requires the C runtime (CRT). They both reside in the libstdc++.a static library. This means that libA.so and libB.so have separate CRT data structures. In particular, the heap used by libA.so is different from the heap used by ...



Only top voted, non community-wiki answers of a minimum length are eligible