Name custom LinkedList type - c++

This is a question of Best practices.
I have implemented a LinkeList (https://github.com/ivanseidel/LinkedList) and it works fine.
The thing is, I'm writing a code that is repeatedly having things like: LinkedList<Beat>, which in my case, is a Rithm, but Rithm is not a type, class or anything, it's just how I see it.
I want a way of simplifying that name, without creating an extended class of LinkedList or anything. Just some way of replacing it.
I have tried with typedef:
typedef LinkedList<Beat> Rithm;
And also with a define (NAHH... I don't like it either)
#define Rithm LinkedList<Beat>
Is there a "correct" way of doing this?

typedef wiki also says the same:
The purpose of typedef is to form complex types from more-basic machine types1 and assign simpler names to such combinations. They are most often used when a standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another.
One should give some thought to naming the typedef as well.
I use the naming conventions used in Dave Hanson's C Interfaces and Implementations: a type is named with the module name and a capital T. So for example, the type of sequences is Seq_T, and the type of hash tables is Table_T.

Related

C++ alias for a global variable/instance object of a class

I have this, a header file with class declaration and one global object instance:
struct ClassName
{
};
extern ClassName ClassObject;
But in CPP codes I'd like to access it via shorter name, for example CO instead of ClassObject
Ideally I'd like to do something like typedef ClassObject CO; but it's not supported
I don't want to use #define CO ClassObject because it's dangerous.
I don't want to use
extern ClassName &CO;
ClassName &CO=ClassObject;
Because that would decrease performance, accessing CO would have to lookup the address value first, while ClassObject wouldn't have to. So using ClassObject would be faster than CO, but I need same performance.
Tried with a union
union
{
ClassName ClassObject;
ClassName CO;
};
but it requires union to be static, so can't declare in header and share across other CPP files.
So there's no solution for this?
This is an unfortunately common design malady, wherein a programmer arbitrarily defines the problem so narrowly that they define away all possible solutions to that problem.
Macros are deemed "dangerous", despite there not actually being anything especially dangerous about this particular macro; it's just a name that turns into a different name (being only two letters is conceptually dangerous, but no more so than using a 2-letter identifier). So it is disregarded, even though it is workable solution (aside from the lack of namespace scoping, but you almost certainly aren't interested in that since you want the name to be as short as possible).
References are deemed to "decrease performance", despite a lack of evidence for references being slow in this particular case nor of the performance of your application being materially affected by an indirect access to a globally accessible object. So it is disregarded, even though this is a perfectly valid use of references in C++ and is directly analogous to type aliases.
If you start from the presupposition that all of the good solutions are bad, then you're obviously not going to be left with any good solutions. And that's where you find yourself.
But really, the best solution is to avoid creating tiny aliases for variables like this to begin with. It's one thing to create aliases for complex template classes like std::vector<int, MyAllocator<int>> and so forth, where there is a huge amount of cruft and verbiage spent on something that's much simpler than it appears. It's quite another to abbreviate an object name, particularly if the abbreviation is as short as 2 letters.
If the 2 letter name is an adequately descriptive name within this context, then that's what it should always be called. If the long name is long because it needs to be that long in order to be adequately descriptive, then odds are good that this descriptiveness will be important everywhere it gets used. And regardless of how you implement this alias, having two names for the same object in the same scope will get confusing to someone who has to read this code and figure out what it's doing. And that "someone" may well be your future self.
So just... don't do this.
only this "extern ClassName &CO;" would be in the header. So when compiling CPP files, they wouldn't know to what CO actually points.
If that really, really, really bothers you, C++17 offers inline variables, which would allow you to put inline ClassName &CO = ClassObject; in your headers.

What is the purpose of boost::fusion?

Ive spent the day reading notes and watching a video on boost::fusion and I really don't get some aspects to it.
Take for example, the boost::fusion::has_key<S> function. What is the purpose of having this in boost::fusion? Is the idea that we just try and move as much programming as possible to happen at compile-time? So pretty much any boost::fusion function is the same as the run-time version, except it now evaluates at compile time? (and we assume doing more at compile-time is good?).
Related to boost::fusion, i'm also a bit confused why metafunctions always return types. Why is this?
Another way to look at boost::fusion is to think of it as "poor man introspection" library. The original motivation for boost::fusion comes from the direction of boost::spirit parser/generator framework, in particular the need to support what is called "parser attributes".
Imagine, you've got a CSV string to parse:
aaaa, 1.1
The type, this string parses into, can be described as "tuple of string and double". We can define such tuples in "plain" C++, either with old school structs (struct { string a; double b; } or newer tuple<string, double>). The only thing we miss is some sort of adapter, which will allow to pass tuples (and some other types) of arbitrary composition to a unified parser interface and expect it to make sense of it without passing any out of band information (such as string parsing templates used by scanf).
That's where boost::fusion comes into play. The most straightforward way to construct a "fusion sequence" is to adapt a normal struct:
struct a {
string s;
double d;
};
BOOST_FUSION_ADAPT_STRUCT(a, (string, s)(double, d))
The "ADAPT_STRUCT" macro adds the necessary information for parser framework (in this example) to be able to "iterate" over members of struct a to the tune of the following questions:
I just parsed a string. Can I assign it to first member of struct a?
I just parsed a double. Can I assign it to second member of struct a?
Are there any other members in struct a or should I stop parsing?
Obviously, this basic example can be further extended (and boost::fusion supplies the capability) to address much more complex cases:
Variants - let's say parser can encounter either sting or double and wants to assign it to the right member of struct a. BOOST_FUSION_ADAPT_ASSOC_STRUCT comes to the rescue (now our parser can ask questions like "which member of struct a is of type double?").
Transformations - our parser can be designed to accept certain types as parameters but the rest of the programs had changed quite a bit. Yet, fusion metafunctions can be conveniently used to adapt new types to old realities (or vice versa).
The rest of boost::fusion functionality naturally follows from the above basics. fusion really shines when there's a need for conversion (in either direction) of "loose IO data" to strongly typed/structured data C++ programs operate upon (if efficiency is of concern). It is the enabling factor behind spirit::qi and spirit::karma being such an efficient (probably the fastest) I/O frameworks .
Fusion is there as a bridge between compile-time and run-time containers and algorithms. You may or may not want to move some of your processing to compile-time, but if you do want to then Fusion might help. I don't think it has a specific manifesto to move as much as possible to compile-time, although I may be wrong.
Meta-functions return types because template meta-programming wasn't invented on purpose. It was discovered more-or-less by accident that C++ templates can be used as a compile-time programming language. A meta-function is a mapping from template arguments to instantiations of a template. As of C++03 there were are two kinds of template (class- and function-), therefore a meta-function has to "return" either a class or a function. Classes are more useful than functions, since you can put values etc. in their static data members.
C++11 adds another kind of template (for typedefs), but that is kind of irrelevant to meta-programming. More importantly for compile-time programming, C++11 adds constexpr functions. They're properly designed for the purpose and they return values just like normal functions. Of course, their input is not a type, so they can't be mappings from types to something else in the way that templates can. So in that sense they lack the "meta-" part of meta-programming. They're "just" compile-time evaluation of normal C++ functions, not meta-functions.

unique synthesised name

I would like to generate various data types in C++ with unique deterministic names. For example:
struct struct_int_double { int mem0; double mem1; };
At present my compiler synthesises names using a counter, which means the names don't agree when compiling the same data type in distinct translation units.
Here's what won't work:
Using the ABI mangled_name function. Because it depends already on structs having unique names. Might work in C++11 compliant ABI by pretending struct is anonymous?
Templates eg struct2 because templates don't work with recursive types.
A complete mangling. Because it gives names which are way too long (hundreds of characters!)
Apart from a global registry (YUK!) the only thing I can think of is to first create a unique long mangled name, and then use a digest or hash function to shorten it (and hope there are no clashes).
Actual problem: to generate libraries which can be called where the types are anonymous, eg tuples, sum types, function types.
Any other ideas?
EDIT: Addition description of recursive type problem. Consider defining a linked list like this:
template<class T>
typedef pair<list<T>*, T> list;
This is actually what is required. It doesn't work for two reasons: first, you can't template a typedef. [NO, you can NOT use a template class with a typedef in it, it doesn't work] Second, you can't pass in list* as an argument because it isn't defined yet. In C without polymorphism you can do it:
struct list_int { struct list_int *next; int value; };
There are several work arounds. For this particular problem you can use a variant of the Barton-Nackman trick, but it doesn't generalise.
There is a general workaround, first shown me by Gabrielle des Rois, using a template with open recursion, and then a partial specialisation to close it. But this is extremely difficult to generate and would probably be unreadable even if I could figure out how to do it.
There's another problem doing variants properly too, but that's not directly related (it's just worse because of the stupid restriction against declaring unions with constructable types).
Therefore, my compiler simply uses ordinary C types. It has to handle polymorphism anyhow: one of the reasons for writing it was to bypass the problems of C++ type system including templates. This then leads to the naming problem.
Do you actually need the names to agree? Just define the structs separately, with different names, in the different translation units and reinterpret_cast<> where necessary to keep the C++ compiler happy. Of course that would be horrific in hand-written code, but this is code generated by your compiler, so you can (and I assume do) perform the necessary static type checks before the C++ code is generated.
If I've missed something and you really do need the type names to agree, then I think you already answered your own question: Unless the compiler can share information between the translation of multiple translation units (through some global registry), I can't see any way of generating unique, deterministic names from the type's structural form except the obvious one of name-mangling.
As for the length of names, I'm not sure why it matters? If you're considering using a hash function to shorten the names then clearly you don't need them to be human-readable, so why do they need to be short?
Personally I'd probably generate semi-human-readable names, in a similar style to existing name-mangling schemes, and not bother with the hash function. So, instead of generating struct_int_double you might generate sid (struct, int, double) or si32f64 (struct, 32-bit integer, 64-bit float) or whatever. Names like that have the advantage that they can still be parsed directly (which seems like it would be pretty much essential for debugging).
Edit
Some more thoughts:
Templates: I don't see any real advantage in generating template code to get around this problem, even if it were possible. If you're worried about hitting symbol name length limits in the linker, templates can't help you, because the linker has no concept of templates: any symbols it see will be mangled forms of the template structure generated by the C++ compiler and will have exactly the same problem as long mangled names generated directly by the felix compiler.
Any types that have been named in felix code should be retained and used directly (or nearly directly) in the generated C++ code. I would think there are practical (soft) readability/maintainability constraints on the complexity of anonymous types used in felix code, which are the only ones you need to generate names for. I assume your "variants" are discriminated unions, so each component part must have a name (the tag) defined in the felix code, and again these names can be retained. (I mentioned this in a comment, but since I'm editing my answer I might as well include it)
Reducing mangled-name length: Running a long mangled name through a hash function sounds like the easiest way to do it, and the chance of collisions should be acceptable as long as you use a good hash function and retain enough bits in your hashed name (and your alphabet for encoding the hashed name has 37 characters, so a full 160-bit sha1 hash could be written in about 31 characters). The hash function idea means that you won't be able to get directly back from a hashed name to the original name, but you might never need to do that. And you could dump out an auxiliary name-mapping table as part of the compilation process I guess (or re-generate the name from the C struct definition maybe, where it's available). Alternatively, if you still really don't like hash functions, you could probably define a reasonably compact bit-level encoding (then write that in the 37-character identifier alphabet), or even run some general purpose compression algorithm on that bit-level encoding. If you have enough felix code to analyse you could even pre-generate a fixed compression dictionary. That's stark raving bonkers of course: just use a hash.
Edit 2: Sorry, brain failure -- sha-1 digests are 160 bits, not 128.
PS. Not sure why this question was down-voted -- it seems reasonable to me, although some more context about this compiler you're working on might help.
I don't really understand your problem.
template<typename T>
struct SListItem
{
SListItem* m_prev;
SListItem* m_next;
T m_value;
};
int main()
{
SListItem<int> sListItem;
}

Internal typedefs in C++ - good style or bad style?

Something I have found myself doing often lately is declaring typedefs relevant to a particular class inside that class, i.e.
class Lorem
{
typedef boost::shared_ptr<Lorem> ptr;
typedef std::vector<Lorem::ptr> vector;
//
// ...
//
};
These types are then used elsewhere in the code:
Lorem::vector lorems;
Lorem::ptr lorem( new Lorem() );
lorems.push_back( lorem );
Reasons I like it:
It reduces the noise introduced by the class templates, std::vector<Lorem> becomes Lorem::vector, etc.
It serves as a statement of intent - in the example above, the Lorem class is intended to be reference counted via boost::shared_ptr and stored in a vector.
It allows the implementation to change - i.e. if Lorem needed to be changed to be intrusively reference counted (via boost::intrusive_ptr) at a later stage then this would have minimal impact to the code.
I think it looks 'prettier' and is arguably easier to read.
Reasons I don't like it:
There are sometimes issues with dependencies - if you want to embed, say, a Lorem::vector within another class but only need (or want) to forward declare Lorem (as opposed to introducing a dependency on its header file) then you end up having to use the explicit types (e.g. boost::shared_ptr<Lorem> rather than Lorem::ptr), which is a little inconsistent.
It may not be very common, and hence harder to understand?
I try to be objective with my coding style, so it would be good to get some other opinions on it so I can dissect my thinking a little bit.
I think it is excellent style, and I use it myself. It is always best to limit the scope of names as much as possible, and use of classes is the best way to do this in C++. For example, the C++ Standard library makes heavy use of typedefs within classes.
It serves as a statement of intent -
in the example above, the Lorem class
is intended to be reference counted
via boost::shared_ptr and stored in a
vector.
This is exactly what it does not do.
If I see 'Foo::Ptr' in the code, I have absolutely no idea whether it's a shared_ptr or a Foo* (STL has ::pointer typedefs that are T*, remember) or whatever. Esp. if it's a shared pointer, I don't provide a typedef at all, but keep the shared_ptr use explicitly in the code.
Actually, I hardly ever use typedefs outside Template Metaprogramming.
The STL does this type of thing all the time
The STL design with concepts defined in terms of member functions and nested typedefs is a historical cul-de-sac, modern template libraries use free functions and traits classes (cf. Boost.Graph), because these do not exclude built-in types from modelling the concept and because it makes adapting types that were not designed with the given template libraries' concepts in mind easier.
Don't use the STL as a reason to make the same mistakes.
Typedefs are the ones what policy based design and traits built upon in C++, so The power of Generic Programming in C++ stems from typedefs themselves.
Typdefs are definitely are good style. And all your "reasons I like" are good and correct.
About problems you have with that. Well, forward declaration is not a holy grail. You can simply design your code to avoid multi level dependencies.
You can move typedef outside the class but Class::ptr is so much prettier then ClassPtr that I don't do this. It is like with namespaces as for me - things stay connected within the scope.
Sometimes I did
Trait<Loren>::ptr
Trait<Loren>::collection
Trait<Loren>::map
And it can be default for all domain classes and with some specialization for certain ones.
The STL does this type of thing all the time - the typedefs are part of the interface for many classes in the STL.
reference
iterator
size_type
value_type
etc...
are all typedefs that are part of the interface for various STL template classes.
Another vote for this being a good idea. I started doing this when writing a simulation that had to be efficient, both in time and space. All of the value types had an Ptr typedef that started out as a boost shared pointer. I then did some profiling and changed some of them to a boost intrusive pointer without having to change any of the code where these objects were used.
Note that this only works when you know where the classes are going to be used, and that all the uses have the same requirements. I wouldn't use this in library code, for example, because you can't know when writing the library the context in which it will be used.
Currently I'm working on code, that intensively uses these kind of typedefs. So far that is fine.
But I noticed that there are quite often iterative typedefs, the definitions are split among several classes, and you never really know what type you are dealing with. My task is to summarize the size of some complex data structures hidden behind these typedefs - so I can't rely on existing interfaces. In combination with three to six levels of nested namespaces and then it becomes confusing.
So before using them, there are some points to be considered
Does anyone else need these typedefs? Is the class used a lot by other classes?
Do I shorten the usage or hide the class? (In case of hiding you also could think of interfaces.)
Are other people working with the code? How do they do it? Will they think it is easier or will they become confused?
When the typedef is used only within the class itself (i.e. is declared as private) I think its a good idea. However, for exactly the reasons you give, I would not use it if the typedef's need to be known outside the class. In that case I recommend to move them outside the class.
I recommend to move those typedefs outside the class. This way, you remove direct dependency on shared pointer and vector classes and you can include them only when needed. Unless you are using those types in your class implementation, I consider they shouldn't be inner typedefs.
The reasons you like it are still matched, since they are solved by the type aliasing through typedef, not by declaring them inside your class.

Valid use of typedef?

I have a char (ie. byte) buffer that I'm sending over the network. At some point in the future I might want to switch the buffer to a different type like unsigned char or short. I've been thinking about doing something like this:
typedef char bufferElementType;
And whenever I do anything with a buffer element I declare it as bufferElementType rather than char. That way I could switch to another type by changing this typedef (of course it wouldn't be that simple, but it would at least be easy to identify the places that need to be modified... there'll be a bufferElementType nearby).
Is this a valid / good use of typedef? Is it not worth the trouble? Is it going to give me a headache at some point in the future? Is it going to make maintainance programmers hate me?
I've read through When Should I Use Typedef In C++, but no one really covered this.
It is a great (and normal) usage. You have to be careful, though, that, for example, the type you select meet the same signed/unsigned criteria, or that they respond similarly to operators. Then it would be easier to change the type afterwards.
Another option is to use templates to avoid fixing the type till the moment you're compiling. A class that is defined as:
template <typename CharType>
class Whatever
{
CharType aChar;
...
};
is able to work with any char type you select, while it responds to all the operators in the same way.
Another advantage of typedefs is that, if used wisely, they can increase readability. As a really dumb example, a Meter and a Degree can both be doubles, but you'd like to differentiate between them. Using a typedef is onc quick & easy solution to make errors more visible.
Note: a more robust solution to the above example would have been to create different types for a meter and a degree. Thus, the compiler can enforce things itself. This requires a bit of work, which doesn't always pay off, however. Using typedefs is a quick & easy way to make errors visible, as described in the article linked above.
Yes, this is the perfect usage for typedef, at least in C.
For C++ it may be argued that templates are a better idea (as Diego Sevilla has suggested) but they have their drawbacks. (Extra work if everything using the data type is not already wrapped in a few classes, slower compilation times and a more complex source file structure, etc.)
It also makes sense to combine the two approaches, that is, give a typedef name to a template parameter.
Note that as you're sending data over a network, char and other integer types may not be interchangeable (e.g. due to endian-ness). In that case, using a templated class with specialized functions might make more sense. (send<char> sends the byte, send<short> converts it to network byte order first)
Yet another solution would be to create a "BufferElementType" class with helper methods (convertToNetworkOrderBytes()) but I'll bet that would be an overkill for you.