5 ms·
Wouldn't it just be simpler to fuse off the part of your linker that handles vtables? IIRC That'll kill every C++ feature that's objectionable to someone who li
by bcoates 12y ago
Wouldn't it just be simpler to fuse off the part of your linker that handles vtables? IIRC That'll kill every C++ feature that's objectionable to someone who likes the idea of 'C with templates'
Unless you want a truly simple C template system, in which case aren't the C11 type sensitive macros sufficient?
- loup-vaillant 12y ago> C11 type sensitive macros Hey, that sounds cool. Do you have a link? A quick search doesn't seem to work. The vtables on the other hand I will steer clear from. Closures are way more useful than class based polymorphism. Combine it with parametric polymorphism (templates), and you won't need to subclass anything ever again —okay, I'm exaggerating a little.
- LukeShu 12y agoLook for the "_Generic" keyword. On that topic, it is possible to do cool things with macros with GCC extensions. A simple example of generic macros was discussed about a week ago: https://news.ycombinator.com/item?id=7896280 https://news.ycombinator.com/item?id=7896280
- loup-vaillant 12y agoThanks. Doesn't look like that's enough for my purposes, though.
- yoklov 12y agoIt's called _Generic (which should be easier to Google), but the fact that you have to modify the macro wherever you want to use it with a new type severely limits its usefulness.
- blt 12y agoAren't std::functions effectively using something like vtables though?
- loup-vaillant 12y agostd::function looks like a regular template class (like any container). And It doesn't look like we should subclass it. So, unless I'm missing something, there is no vtable.
- Sharlin 12y agostd::function is usually implemented using subtype polymorphism internally.
- loup-vaillant 12y agoOkay… By the way, why do we need std::function at all? Every time I saw it, it was to work around some dark corner of C++ type system or template dark magic.
- detrino 12y agoMost programming languages implicitly type erase closures, C++ does not. Type erasure can come at the cost of heap allocation and indirect function calls. If you need type erasure in C++ you can put any callable type inside std::function.
- 72deluxe 12y agoIs it because everyone was thrown by the syntax of function pointers (for no good reason, other than they never encountered them)?
- cheez 12y agoBecause function pointers in C++ carry no state. Given: class A { void foo(); }; A a; There is no such construct that lets you store a call to foo specialized for the instance 'a': ??? thing = a.foo; // doesn't exist The only option in C++ is to take the address of the member function: &A::foo But even this is not sufficient as it is equivalent to: void (*)(A * __this) That is, the "this" pointer is not stored. Along comes mem_fun: struct mem_fun{ A *a; void(A::*ptr)(); }; Now you can store a call to foo for the instance a: mem_fun fun; fun.a = &a; fun.ptr = &A::foo; Adding an operator() to mem_fun lets you treat a mem_fun instance as a function: void operator()(){ a->*ptr(); } ... fun() Now, lets say you need to store this as a generic "callback". Well, how would you do that? Sure, you can store mem_fun instances but what about just plain function pointers? Now you can't store them. In comes std::function. With a little bit of VERY simple to understand magic, you can do: std::function<void()> foo = fun; // mem_fun std::function<void()> foo2 = global_fun; // simple member pointer
- detrino 12y agoType erased closures are strictly less useful than subtype polymorphism + virtual functions (another form of type erasure) as the latter allows you to share data among an entire interface.
- loup-vaillant 12y agoClosures are simpler, and therefore less cumbersome for 90% of the use cases. I prefer this compromise over the other. Also, I'm not sure I get this "type erasure" business. In ML languages, there is no such erasure. I guess you need this erasure because the language doesn't support parametric polymorphism to begin with? I'm thinking about Java, which hacked generics after the fact, and maintained backward compatibility through type erasure. In C++, there are few type erasures. Generally, when we want a function to receive a closure, we write it like this (minus dark corner I have missed): template <typename T, typename E> for_each(T functor, vector<E>); No base class in sight there, just lots of duplicated object code. (Which is better is left as an exercise to the reader.)