8 ms·
I'm a bit frightened with the move toward adding a compile-time sublanguage. Frightened because I feel it will end up being half-baked and then abandoned like o
by KKKKkkkk1 10y ago
I'm a bit frightened with the move toward adding a compile-time sublanguage. Frightened because I feel it will end up being half-baked and then abandoned like other C++ features (virtual inheritance for example).
As an example, I've been exploring Sean Parent's idea of concept-based polymorphism that allows you to implement "virtual functions" that get bound at compile time. To make this scheme explicit, I need to assert in the base class that all my "derived" classes implement a method with a certain signature. Does C++ allow me to do this?
- quotemstr 10y ago> adding a compile-time sublanguage. The C++ template system is already a Turing-complete functional programming language and has been since C++'s inception. I see nothing wrong with making this language's syntax more convenient. > half-baked and then abandoned like other C++ features (virtual inheritance for example) Virtual inheritance has its place. It's part of the language and works fine. What would you change?
- deleted 10y ago[deleted]
- vvanders 10y agoVirtual inheritance means you have a diamond pattern and haven't separated your components properly. It should have never made it into the language as far as I'm concerned.
- quotemstr 10y agoThat's a matter of taste; opinions differ. One perhaps less controversial case for virtual inheritance is in exceptions: see http://www.boost.org/doc/libs/1_53_0/libs/exception/doc/using_virtual_inheritance_in_exception_types.html http://www.boost.org/doc/libs/1_53_0/libs/exception/doc/usin...
- ioquatix 10y agoIt's useful for interfaces, e.g. virtual public IFoo, is it not?
- frozenport 10y agoInterfaces should have been compile time, but for reasons I don't know, they weren't implemented as such
- evanpw 10y agoWhat would that mean? No dynamic dispatch at all?
- frozenport 10y agoIt's possible to perform compile time de-virtualization. Half the time virtual is used to enforce inheritance rather than virtual dispatch.
- bubuga 10y ago> Virtual inheritance means you have a diamond pattern and haven't separated your components properly. I've seen this argument pop out time and again as if it was a mantra of sorts, and more often than not it comes from someone with a background almost exclusively founded on Java. Their line of reasoning essentially boils down to "Java doesn't support it, the people behind Java said something about it, therefore it's bad". But C++ isn't Java, nor does Java dictate what is correct or what makes sense. Particularly when the only assertion you could come up with to criticize multiple inheritance was a comment that had nothing to do with C++ or even OO programming, but only to do with your personal taste regarding your superficial impressions regarding software design.
- vvanders 10y agoOoo, that Java remark burns. I've only touched Java seriously in the last few years of my career, I'm a hardcore C++/native type. Here's the issues I take with virtual inheritance: 1. It complicates the vtable and function/member calls leading to another level of indirection, so from a performance perspective it's a negative mark. 2. The more fundamental problem is that you've botched the hasA vs isA association. If you have two classes that share a base class then that base class should be refactored into a component that can then be used as a member without polluting the class hierarchy. This leads to better composability since you can now pass this object around without pulling a whole class hierarchy with it. You're welcome to use virtual inheritance all you want in your projects but much like knowing what subset of C++ to use(and what not) you'll never see it in code I work on.
- quotemstr 10y ago> you've botched the hasA vs isA association No you haven't. In many senses, C++ inheritance is just shorthand for composition. That's why things like private inheritance are useful. Through this lens, virtual inheritance is automatic composition in which multiple composed objects each have a pointer to some shared object (the virtual base). It doesn't mess with hasA vs. isA at all. > knowing what subset of C++ to use This idea that a good coding standard necessarily bans parts of C++ has done massive damage to the C++ community. The correct subset of C++ to use is C++. Turning off parts of the language is just a cheap way to look sagacious while infantilizing developers. Every feature has its place.
- Kristine1975 10y ago>I need to assert in the base class that all my "derived" classes implement a method with a certain signature. Does C++ allow me to do this? Of course (C++14, possibly C++11): #include <type_traits> template <typename T, typename... Params> struct HasFoo { // SFINAE will disable this function template if U has no method foo(float) template <typename U> static constexpr bool check(decltype(std::declval<U>().foo(std::declval<Params>()...))*) { // We don't check foo's return type here return true; } // Fallback if above function template is disabled template <typename U> static constexpr bool check(...) { return false; } static constexpr bool value = check<T>(0); }; template <typename D> struct Base { Base() { static_assert(HasFoo<D, float>::value, "D must implement 'foo(float)'"); } }; struct Derived { void foo(int) { } }; Since this essentially simulates a method call, implicit conversions work, as does overloading "foo". As you have to implement "HasFoo" for every method you check, a macro will come in handy, say MAKE_METHOD_CHECK(Foo, bool, float) I added some comments, feel free to ask if something is not clear :-)
- im3w1l 10y agoNice! Now to make the idea of compile time virtual functions real, can you force derived classes to have foo_impl, and have an inlined function foo in the base class that calls foo_impl? What about grand children classes?
- Kristine1975 10y ago>can you force derived classes to have foo_impl, and have an inlined function foo in the base class that calls foo_impl? If that's all you want just write: void foo() { static_cast<Derived&>(*this).foo_impl(); } When the derived class doesn't have any method "foo_impl" (or no "foo_impl" with a suitable signature), you will get a compile-time error. No need for the static_assert, that was just because KKKKkkkk1 asked whether checking for the existence of a method at compile-time was possible. Compile-time polymorphism is essentially duck typing: If it quacks like a duck you can treat it as one. If it doesn't quack like a duck, but you still treat it as one you get a compiler error.
- saynsedit 10y agoThe technique for static polymorphism is known as CRTP in C++
- gpderetta 10y ago"To make this scheme explicit, I need to assert in the base class that all my "derived" classes implement a method with a certain signature. Does C++ allow me to do this?" As the call is resolved at compile time, simply calling the function will cause a compile error if the derived class doesn't implement it. The error message might not be the prettiest, but there are ways to improve that.