Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
Let's suppose I'm writing a compiler for some programming language. It is common to use abstract syntax tree (AST) as an internal representation. I can see two possible ways to design it:
using boost::variant
using inheritance
As hierarchy of nodes is fixed - boost::variant will suffice.
My question is what are the advantages and disadvantages of each approach from points of maintability and runtime efficiency?
Using boost::variants will work, but will require you to use visitor pattern extensively to exploit the content of a variant object. If later you extend the number of types used in your variant, you'll have to maintain all the visitors that you've implemented.
With inheritance, you have the advantage of being able to use polymorphism. Later extension will be straightforward : simply derive one of the existing base and override the polymorphic functions, without touching the rest of the code.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
In this discussion, a poster (mikera) says
There's no dotted pair in Clojure.
A philosophical reason for this is that Clojure avoids the use of a
concrete "pair" data structure and instead emphasises abstract
"sequences" which can have may possible concrete implementations.
Can someone elaborate or point me to some literature on what this means? Is this a more elegant or mathematically pure approach?
Here is a link to a handy list of questions that Rich has answered about his design decisions https://gist.github.com/reborg/dc8b0c96c397a56668905e2767fd697f
While this list doesn't explicitly explain why there is no concrete "pair" data structure it might give you some insight into Rich's preference for practical, general design.
I remember there was a time when there was a discussion about introducing a "tuple" which would have been like a vector that only has two elements to avoid the needless memory allocation that occurs when using a two element vector.
Introducing these things has a complexity cost and so you can assume that the cost/benefit analysis did not warrant adding it to the code base.
Check out this discussion on Clojure's Jira project about adding tuples and you'll see how any idea gets put through its paces:
https://dev.clojure.org/jira/browse/CLJ-1517
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Feels like a question that has been asked before but I'm not exactly sure how to properly word it in a google search. Say I have a MainWindow object and in that object I define several objects PanelA, PanelB, PanelC and PanelD. What's a good way of connecting these objects to each other without having constructors that look like this
PanelA(PanelB* b, PanelC* c, PanelD* d)
Would you suggest to just pass them all in through the main class like so
PanelA(MainWindow* mw)
{
b=mw->b; c=mw->c; d=mw->d;
}
Or is there better ways to structure my classes. What's this problem known as in general, so that I can google this stuff myself.
What's this problem known as in general, so that I can google this stuff myself.
The design defect is known as strong coupling of types and use of hardcoded relations.
The general approach to refactor such code is to introduce interfaces and design patterns to solve the actual dependencies by means of functionality.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have see such answer:
COM is a technique of it's own. It fulfills some special needs but
violates a lot of good engineering principles. E.g solid. The standard
has better ways than using COM. – mkaes
Very interesting to know what is that "better ways"?
We use in our project IUnknown base class, but not COM technology itself.
IUnknown allows us:
have nice specified interface abstract classes;
use its add()/release() as basis for intrusive smart ptrs;
use mechanism of QueryInterface() to be more effective than dynamic_cast;
Okay, exists boost::intrusive_ptr but it is not in the standard so far. And even if it was there, this will be separate class to solve task of intrusive smart ptr. Assuming it is there, yes I could do something as
interface ITable : intrusive_ptr {}
interface IField : intrusive_ptr {}
But what about QueryInterface() mechanism?
P.S. This question is NOT about COM at all.
The standard uses: composition rather than inheritance in most cases (very little inheritance in the standard library). Prefers template based generic programming rather than runtime polymorphism. Prefers value types rather than keeping pointers of unknown ultimate type for everything, everywhere. All things you should be doing in C++ rather than treating it like Java.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
In object oriented languages, it is fairly common to implement ASTs (Abstract Syntax Trees) using simple hierarchies (the Composite pattern), and to traverse them via visitors.
In functional programming languages, using variants/sum types, and then pattern matching, is the right approach.
C++ features both inheritance, and Boost.Variants. I have written several AST hierarchies using inheritance, but I'd like to get some feedback from people who would have used the variant approach. I'd like to know which one is the "best", in terms of performance (time and space), but also in terms of maintainability (easiness to create trees, and to traverse them).
I am especially interested in experience with implementation of hash-consing (keeping a single copy of each common subtree), possibly with Boost.Flyweight.
I am interested in battle field experience, not opinions. This question was original closed as "opinion-based". Which has never been the point...
Thanks!
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
There are certain questions in my mind:
What is the standard for naming pointer to functions as delegates?
What is the best way to define signature of functions in this matter?
What are the techniques of maintaining safety and stability of code
when using this pointers?
There is no standard for such naming, only conventions that vary from project to project (or company to company). Common rules include avoiding leading underscores in such names (reserved for the standard library)
There is no best way to "define a signature", it's the same as for any other functions: choose explicit and clear names for both the method name and its arguments.
The best advise is to avoid explicit pointers to functions, and prefer using std::function , a powerful polymorphic function wrapper.