Is Typelist(in the sense of Alexandrescu define it) mainly/essentialy useful for generate hierarchy of class (and maybe for class like boost::tuple )
or is there plenty of other domains where typelist is very useful ?
Its also used in Mixin-Based Programming in C++ described by Ulrich W. Eisenecker, Frank Blinn, and Krzysztof Czarneck.
I believe you're referring to something like a linked list of templates.
This is a fundamental structure in template metaprogramming. Template metaprogramming has various applications, where the programmer encodes a problem in templates and the metaprogram implements an algorithm to solve it.
Boost Spirit is often cited as a prime example of template metaprogramming, although unfortunately I can't tell you much about it.
It seems to me that typelists are most useful as a building block for other generic libraries rather than being used directly in client code. Don't use a lower-level tool if Boost tuples or MPL are flexible enough to do what you need. But there's nothing to say you couldn't use typelists directly if you need that kind of flexibility.
We use a typelist as a sort of type-safe composition, but where each child is accessible through a single interface:
// Defining a typelist:
typedef TypeList<A,
TypeList<B,
TypeList<C, NullType> > > MyTypeList;
MyTypeList tl;
// Setting values in the typelist:
A a;
tl.set(a);
C c;
tl.set(c);
tl.tail().head() = newB;
// Retrieving values from the typelist:
C c = tl.get<C>();
B b = tl.tail().head();
// To reinitialize a value:
tl.reset<B>();
tl.set(B());
// To get total size:
int size = tl.count();
Beyond that, there's an interface for iterating and built-in support for functors.
The benefit is that you can either treat the children independently or homogeneously, depending on the need.
The downside is that you sacrifice a certain amount of abstractness. Things become much more concrete. It also introduces a new way of dealing with composition, which is something new to learn for others who need to work with the code.
For us, in the place we used it, it was a good fit.
Related
Way back when I was writing Delphi, there was a TStringList which was basically a map of strings to Delphi's generic TObject. Using this structure, I could easily make a recursive, hierarchical structure by placing another TStringList against one of the string keys:
ParentStringList["somekey"] = "just a string value";
ParentStringList["anotherkey"] = SomeChildStringList;
Question is, how do I achieve the same thing in C++?
What I have at the moment is:
typedef boost::variant< std::string, my_dictionary > my_variant;
typedef std::map < std::string, my_variant > my_dictionary;
... which is clearly circular.
Can I do this without wrapping things in structs (which I can forward declare), or without using pointers (which the compiler knows the size of)?
The Boost.Variant documentation covers this exact case. You can't do it without using pointers or some other similar wrapper.
This approach could work:
struct my_variant;
typedef map<string,my_variant> my_dict;
struct my_variant: variant<string, my_dict>
{};
There are a few issues with it though:
This requires containers (std::map specifically) that allow template arguments that are not fully defined. Using C++98, this is explicitly forbidden, I'm not sure if this was lifted in later C++ versions.
Publicly deriving from containers is not usually a good idea, please research the reasons for that yourself and how they apply to your program. Using containment instead of derivation would be a safer alternative, or the middle way of private derivation, but that breaks the useful IS-A relationship that this approach provides.
Try using vectors. I've used them before as internal representations of an external database within my program as a data structure.
Is it possible to use template meta-programming to convert any struct or class into a tuple?
For instance:
struct Foo
{
char c;
int i;
std::string s;
};
typedef std::tuple< char, int, std::string > Foo_Tuple;
It would be nice to have some template code which will generate Foo_Tuple automagically for me.
ANSWER
This is overkill for such a simple case, but for more elaborate cases (eg ORM or any time you need to write a lot of boiler-plate code, and a mere template or macro is inadequate for the task), Boost Mirror looks like it may be extremely useful. I have dug into Boost Mirror a bit more: the basic reflection functionality (in Mirror and Puddle) are not hard to understand, are quite easy to set-up and seem to be quite extensive (can handle many constructs, including C++11 enum classes, etc...). I find this basic functionality to be more than adequate - I can just use the MACROS to the extent that I want to expose my classes to Reflection (so that I don't have to write boiler-plate code). The Factory generators also seem to be very powerful (with the same initial macros set up, you can swap in any factory generator you like to output JSON, SOCI, or to a stream etc...), but has a larger learning curve/setup, if you want to write your own factory generators. One last couple of notes: with some minor tweaks, I was able to get it to work with C++11 on gcc 4.7.2; also, the documentation has been well DOxygenated and there seem to be more than sufficient examples to get going quickly.
I don't think that there's a way to do this in C++.
I don't know a way to enumerate the fields/types in a struct - if you could do that, I would think that constructing such a tuple would be fairly straightforward.
I believe that Boost.Fusion has a macro that helps with this called FUSION_ADAPT_STRUCT, but that's all manual.
The technical term for this is "reflection", and you can find lots of information about it by searching for "C++ reflection".
Here's one such article: How can I add reflection to a C++ application?
Do you recommend learning C++ using a template?
Edit
I have basic programming language (I know how to work with things like loops, arrays, classes and functions) and I have been recommended to follow tutorials in a template that is already made for creating games.
I would like to become a game programmer.
No. C++ template is the last that newbies should touch. First learn the basics: loops, conditional blocks, various syntax, then class/struct. And then templates! However, you should learn to use STL, almost from the beginning. Please note that using templates (such as STL) is one thing, and writing your own class/function templates is another. First learn to write non-template class and function. Once you're confident, only then start learning and writing your own class and function templates!
Buy any introductory book, as listed here, and start reading it:
The Definitive C++ Book Guide and List
The short answer to your question is yes.
The longer answer is yes, BUT you need to consider when to move into the C++ template world. C++ is a very rich languare and comes with enormous power and possibilities. To use this power one needs responsibility and one must have the knowledge to use things wisely. There are many things one needs to understand in C++ in order to write good code and templates is not in the list of most important things.
However, as already mentioned STL (Standard Template Library) is somewhat a central piece in C++ and is, as you see from the name, a library using templates (heavily). In my opinion, STL is something you should start looking at when you start learning C++. For this you will need to understand basic concepts about templates. The same goes for boost, which is a masterpiece in C++ template programming. Here you might need even more understanding what templates are, what they look like and what they do.
My advice is to start by learning the C++ fundamentals without involving templates. This is by itself a big domain and will take a long time to master. When you feel comfortable here, take a look at STL and maybe later boost. Here you can get familiar with template programming as a user of templates in your code. Again, these libraries are big and require work to understand properly so you can use them wisely in your own code.
Here is a nice article about programming in general and what it takes to learn something. C++ is not an exception and requires a lot of time and work.
My own experience in C++ is soon 10 years and I still have a lot to learn, especially about templates. I use them daily, but always try to see when they actually make sence to use. I'm not now talking about using STL or boost, because this I believe is part of my C++ base toolkit. I'm talking about writing my own templated code. What I have seen where I've worked is that people many times have problems with templates and making good software. In my opinion, only a master knows when to be in the template world, when not to and how to combine the two.
Still, templates are very useful and I believe all C++ programmers should have some understanding of them. That level of understanding depends on their own usage of templates and over time you will yourself decide what you use from C++'s huge toolkit.
C++ templates - The Complete Guide is considered the book about templates and is definitely worth a read (or many;)).
Yes, you should learn the template aspects of C++ programming, since the majority of the standard is based on templates. For instance, you are much better off learning about arrays via the std::vector<T> class template or possibly the more recent std::tr1::array<T>, than using raw C-style arrays.
Note that what I am recommending is that you use template-based libraries that have been provided for you. You most definitely should not start learning by trying to write template code yourself, which requires a fair bit of background knowledge to get right. In particular, writing exception-safe template classes is a tricky process that took the C++ community years to get their collective heads around.
Templates gives the powerful feature of generic programming to C++. So, you should not neglect it.
The basics of templates is very simple: just writing code where one or more of the types or values is initially left unspecified, but will be explicitly specified sometimes before compilation. It's very easy to write and understand simple uses of templates, so don't let yourself be scared off.
For example of how simple it can be to get something genuinely useful, say you have two structures representing incoming network messages A and B and they contain a significant set of same-named fields, even though the exact types and position in the structures vary, you might write reusable code to extract those fields into some internal structure I as in:
struct X { int k : 5; char m[2]; float l; bool only_in_x; };
struct Y { int k; double l; char m[4]; };
struct I { int k; double l; char m[4]; size_t m_len; bool only_from_x; };
template <class T>
void load_common_fields(I& i, const T& t)
{
i.k = t.k;
i.l = t.l;
memcpy(i.m, t.m, t.m_len = sizeof t.m);
}
In the code handling incoming messages, you can then do something like...
switch (network_message.message_type)
{
case X:
{
X* p_x = (X*)buffer;
load_common_fields(i, x);
i.only_from_x = p_x.only_in_x;
break;
}
case Y:
{
Y* p_y = (Y*)buffer;
load_common_fields(i, y);
break;
}
}
This is much simpler and faster than using run-time polymorphism, with virtual functions and common base classes. Why not use it? It's less ugly but effectively equivalent to - and hopefully easy understood by comparison to - using a preprocessor macro to generate functions for each type involved ala:
#define LOAD_COMMON_FIELDS(T) \
void load_common_fields(I& i, const T& t) \
{ \
...
When you're very comfortable with such simple uses start playing with SFINAE, CRTP, meta-progamming, policy-based design etc. as you naturally observe repeating issues with your code and get that "oh, I can see how that's useful" feeling as you read about them. If you read about something in your programming studies and you can't see practical ways it could have helped in your recent projects, then you may not be ready for it yet.
No, It should be last. Learn the basic functionality first. I have given link. you can learn from it.
http://www.cplusplus.com/doc/tutorial/
Do you mean the template mechanism of C++? Yes you should definitely learn this feature, because it is one of the key concepts of C++. You will get in touch with the so called "Standard Template Library (STL)" very soon, for example when you want to handle a vector of data.
See the following references for an introduction:
http://en.wikipedia.org/wiki/Standard_Template_Library
http://www.sgi.com/tech/stl/
You should at least understand the concept of the template mechanism in order to understand the basic container and algorithm templates of the STL.
Nevertheless, you should learn the C++ language itself first.
What are the advantages of using boost.any library ? Could you please give me some real life examples ? Why the same functionality couldn't be achieved by having some generic type in the root of object's hierarchy and creating containers with that base type ?
boost::any will happily store ints and floats, types that clearly have no base classes. A real-life example where you can use it is a virtual machine for a high-level interpreted language. Your "function" objects will need an array of arguments. This can easily be implemented with a std::list<boost::any> behind the scenes.
I consider that Boost.Variant should always be preferred as it's non-intrusive and still calls for very structured programming.
But i guess the main idea behind boost.any is to provide the equivalent of java and c# object types. It's a way of saying "yes we can" ! :-)
We've used it in a property map, (std::map<std::string, boost::any>), to store a lot of things dynamically in a simple, flat dataspace.
Mostly we either stored smart-ptr-to-scriptable-objects or strings, but some entries where other types (floats, vec3f, matrices, and other non-standard objects).
It works pretty well for adding more dynamic capabilities to c++, or wherever you want some type-erasure to just add any type of data to an object.
Why the same functionality couldn't be achieved by having some generic type in the root of object's hierarchy and creating containers with that base type ?
That calls an object hierarchy -- a construct you are injecting in artificially in to the design for solving a peripheral problem. Further, such a construct is easy to get wrong and a wrong implementation can wreak havoc. Boost.Any is a community reviewed safe, well-tested alternative.
Could you please give me some real life examples ?
TinyJSON uses boost.Any.
What are the advantages of using boost.any library ?
I refer the introductory documentation.
We use boost.any as the carrier type for a type-safe tagged variadic container. Here's what that means:
We have a "raft" object, which travels through a set of filters. When a filter wants to add data to the raft, it can do something like this:
raft.addTaggedData<ETag1>(3.0);
raft.addTaggedData<ETag2>("a string")`;
std::string str = raft.getTaggedData<ETag2>();
int a = raft.getTaggedData<ETag1>(); // <-- Compile error
Where ETag1 and ETag2 are members of an enum, and we use a traits template to map tags to types.
The raft class is using a list of pair<ETagType, boost::any> as a backing store. Boost.any saved us the pain of managing raw buffers for various types.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I discovered template metaprogramming more than 5 years ago and got a huge kick out of reading Modern C++ Design but I never found an opertunity to use it in real life.
Have you ever used this technique in real code?
Contributors to Boost need not apply ;o)
I once used template metaprogramming in C++ to implement a technique called "symbolic perturbation" for dealing with degenerate input in geometric algorithms. By representing arithmetic expressions as nested templates (i.e. basically by writing out the parse trees by hand) I was able to hand off all the expression analysis to the template processor.
Doing this kind of thing with templates is more efficient than, say, writing expression trees using objects and doing the analysis at runtime. It's faster because the modified (perturbed) expression tree is then available to the optimizer at the same level as the rest of your code, so you get the full benefits of optimization, both within your expressions but also (where possible) between your expressions and the surrounding code.
Of course you could accomplish the same thing by implementing a small DSL (domain specific language) for your expressions and the pasting the translated C++ code into your regular program. That would get you all the same optimization benefits and also be more legible -- but the tradeoff is that you have to maintain a parser.
I've found policies, described in Modern C++ Design, really useful in two situations:
When I'm developing a component that I expect will be reused, but in a slightly different way. Alexandrescu's suggestion of using a policy to reflect a design fits in really well here - it helps me get past questions like, "I could do this with a background thread, but what if someone later on wants to do it in time slices?" Ok fine, I just write my class to accept a ConcurrencyPolicy and implement the one I need at the moment. Then at least I know the person who comes behind me can write and plug in a new policy when they need it, without having to totally rework my design. Caveat: I have to reign myself in sometimes or this can get out of control -- remember the YAGNI principle!
When I'm trying to refactor several similar blocks of code into one. Usually the code will be copy-pasted and modified slightly because it would have had too much if/else logic otherwise, or because the types involved were too different. I've found that policies often allow for a clean one-fits-all version where traditional logic or multiple inheritance would not.
I've used it in the inner loops of a game's graphics code, where you want some level of abstraction and modularity but can't pay the cost of branches or virtual calls. Overall it was a better solution than a proliferation of handwritten special-case functions.
Template metaprogramming and expression templates are becoming more popular in the scientific community as optimization methods that offload some of the computational effort onto the compiler while maintaining some abstraction. The resulting code is larger and less readable, but I have used these techniques to speed up linear algebra libraries and quadrature methods in FEM libraries.
For application-specific reading, Todd Veldhuizen is a big name in this area. A popular book is C++ and Object Oriented Numeric Computing for Scientists and Engineers by Daoqi Yang.
Template meta programming is a wonderful and power technique when writing c++ libraries. I've used it a few time in custom solutions, but usually a less elegant old style c++ solution is easier to get through code review and easier to maintain for other users.
However, I've got a lot of mileage out of template meta programming when writing reusable components/libraries. I'm not talking anything as large some of Boost's stuff just smallish components that will be reused frequently.
I used TMP for a singleton system where the user could specify what type of singleton they desired. The interface was very basic. Underneath it was powered by heavy TMP.
template< typename T >
T& singleton();
template< typename T >
T& zombie_singleton();
template< typename T >
T& phoenix_singleton();
Another successful use was simplifying our IPC layer. It is built using classic OO style. Each message needs to derive from an abstract base class and override some serialization methods. Nothing too extreme, but it generates a lot of boiler plate code.
We threw some TMP at it and automated the generation of all the code for the simple case of messages containing only POD data. The TMP messages still used the OO backend but they massively reduce the amount of boiler plate code. The TMP was also used to generate the message vistor. Over time all our message migrated to the TMP method. It was easier and less code to build a simple POD struct just for message passing and add the few (maybe 3) lines needed to get the TMP to generate the classes than it was to derive a new message to send a regular class across the IPC framework.
I use template metaprogramming all the time, but in D, not C++. C++'s template metalanguage was originally designed for simple type parametrization and became a Turing complete metalanguage almost by accident. It is therefore a Turing tarpit that only Andrei Alexandrescu, not mere mortals, can use.
D's template sublanguage, on the other hand, was actually designed for metaprogramming beyond simple type parameterization. Andrei Alexandrescu seems to love it, but other people can actually understand his D templates. It's also powerful enough that someone wrote a compile-time raytracer in it as a proof of concept.
I guess the most useful/non-trivial metaprogram I ever wrote in D was a function template that, given a struct type as the template parameter and a list of column header names in an order corresponding to the variable declarations in the struct as a runtime parameter, will read in a CSV file, and return an array of structs, one for each row, with each struct field corresponding to a column. All type conversions (string to float, int, etc.) are done automatically, based on the types of the template fields.
Another good one, which mostly works, but still doesn't handle a few cases properly, is a deep copy function template that handles structs, classes, and arrays properly. It uses only compile time reflection/introspection, so that it can work with structs, which, unlike full-blown classes, have no runtime reflection/introspection capabilities in D because they're supposed to be lightweight.
Most programmers who use template metaprogramming use it indirectly, through libraries like boost. They don't even probably know what is happening behind the scenes, only that it makes the syntax of certain operations much much easier.
I've used it quite a bit with DSP code, especially FFTs, fixed size circular buffers, hadamard transforms and the like.
For those familiar with Oracle Template Library (OTL), boost::any and Loki library (the one described in Modern C++ Design) here's the proof of concept TMP code that enables you to store one row of otl_stream in vector<boost::any> container and access data by column number. And 'Yes', I'm going to incorporate it in production code.
#include <iostream>
#include <vector>
#include <string>
#include <Loki/Typelist.h>
#include <Loki/TypeTraits.h>
#include <Loki/TypeManip.h>
#include <boost/any.hpp>
#define OTL_ORA10G_R2
#define OTL_ORA_UTF8
#include <otlv4.h>
using namespace Loki;
/* Auxiliary structs */
template <int T1, int T2>
struct IsIntTemplateEqualsTo{
static const int value = ( T1 == T2 );
};
template <int T1>
struct ZeroIntTemplateWorkaround{
static const int value = ( 0 == T1? 1 : T1 );
};
/* Wrapper class for data row */
template <class TList>
class T_DataRow;
template <>
class T_DataRow<NullType>{
protected:
std::vector<boost::any> _data;
public:
void Populate( otl_stream& ){};
};
/* Note the inheritance trick that enables to traverse Typelist */
template <class T, class U>
class T_DataRow< Typelist<T, U> >:public T_DataRow<U>{
public:
void Populate( otl_stream& aInputStream ){
T value;
aInputStream >> value;
boost::any anyValue = value;
_data.push_back( anyValue );
T_DataRow<U>::Populate( aInputStream );
}
template <int TIdx>
/* return type */
Select<
IsIntTemplateEqualsTo<TIdx, 0>::value,
typename T,
typename TL::TypeAt<
U,
ZeroIntTemplateWorkaround<TIdx>::value - 1
>::Result
>::Result
/* sig */
GetValue(){
/* body */
return boost::any_cast<
Select<
IsIntTemplateEqualsTo<TIdx, 0>::value,
typename T,
typename TL::TypeAt<
U,
ZeroIntTemplateWorkaround<TIdx>::value - 1
>::Result
>::Result
>( _data[ TIdx ] );
}
};
int main(int argc, char* argv[])
{
db.rlogon( "AMONRAWMS/WMS#amohpadb.world" ); // connect to Oracle
std::cout<<"Connected to oracle DB"<<std::endl;
otl_stream o( 1, "select * from blockstatuslist", db );
T_DataRow< TYPELIST_3( int, int, std::string )> c;
c.Populate( o );
typedef enum{ rcnum, id, name } e_fields;
/* After declaring enum you can actually acess columns by name */
std::cout << c.GetValue<rcnum>() << std::endl;
std::cout << c.GetValue<id>() << std::endl;
std::cout << c.GetValue<name>() << std::endl;
return 0;
};
For those not familiar with mentioned libraries.
The problem with OTL's otl_stream container is that one can access columns data only in sequential order by declaring variables of appropriate type and applying the operator >> to otl_stream object in the following way:
otl_stream o( 1, "select * from blockstatuslist", db );
int rcnum;
int id;
std::string name;
o >> rcnum >> id >> name;
It's not always convenient. The workaround is to write some wrapper class and to populate it with data from otl_stream. The desire is to be able to declare the list of column types and then:
take the type T of the column
declare variable of that type
apply olt_stream::operator >>(T&)
store the result (in the vector of boost::any)
take the type of the next column and repeat until all columns are processed
You can do all this with the help of Loki's Typelist struct, template specialization and inheritance.
With the help of Loki's library constructs you can also generate bunch of GetValue functions that return values of appropriate type deducing it from column's number (actually number of type in Typelist).
Almost 8 months after asking this I've finally used some TMP, I use a TypeList of interfaces in order to implement QueryInterface in a base class.
I use it with boost::statechart for large statemachines.
Yes I have, mostly to do some things that resemble duck-typing when I was wrapping a legacy API in a more modern C++ interface.
No I haven't used it in production code.
Why?
We have to support 6+ platforms with native platform compilers. It's
hard enough to use STL in this environment let alone modern template
techniques.
Developers don't seem to be keeping up C++ advances anymore. We use C++
when we have to. We have legacy code with legacy designs. New code is
done in something else e.g., Java, Javascript, Flash.
Don't do that. The reason behind that is as follows: by nature of template metaprogramming, if some part of your logic is done at compile-time, every logic that it is dependent on must be done at compile time as well. Once you start it, do one portion of your logic at compile time, there is no return. The snowball will keep on rolling and there is no way to stop it.
For example, you can't iterate on the elements of a boost::tuple<>, because you can only access them at compile time. You must use template metaprogramming to achieve what would have been easy and straightforward C++, and this always happens when the users of C++ aren't careful enough not to move too many things to compile-time. Sometimes it is difficult to see when a certain use of compiletime logic would become problematic, and sometimes programmers are eager to try and test what they've read in Alexandrescu's. In any case, this is a very bad idea in my opinion.
Many programmers don't use templates much because of the poor compiler support up until recently. However, while templates have had a lot of issues in the pas, newer compilers have much better support. I write code that has to work with GCC on Mac and Linux as well as Microsoft Visual C++ and it's only with GCC 4 and VC++ 2005 that these compiler have supported the standard really well.
Generic programming via templates is not something you need all the time but is definitely a useful code to have in your toolbox.
The obvious example container classes but templates are also useful for many other things. Two examples from my own work are:
Smart pointers ( e.g. Reference-counted, copy-on-write, etc.)
Math support classes such as Matrices, vectors, splines, etc. that need to support a variety of data types and still be efficient.