Posts for 2011 May
Cool C++0X features VIII: Variadic wrapper and type inference with decltype
Post by Nico Brailovsky @ 2011-05-31 | Permalink | Leave a comment
The wrapper function we built last time looks something like this now:
#include
void do_something() { std::cout << PRETTY_FUNCTION << "n"; }
void do_something(const char*) { std::cout << PRETTY_FUNCTION << "n"; }
template
void wrap(Args... a) {
std::cout << PRETTY_FUNCTION << "n";
do_something(a...);
}
int main() {
wrap();
wrap("nice");
return 0;
}
But, as we saw last time, this approach has the problem of requiring the return type of do_something to be known before hand. What can we do to remove this dependency? In C++, not much. You can't really declare a type based on the return type of another function. You do have the option of using lots of metaprogramming wizardy, but this is both error prone and ugly (see Stroustroup's C++0x FAQ).
C++0x lets you do some magic with type inference using decltype; decltype(expr) will yield the type of that expression. It works quite similarly as sizeof does; decltype is resolved at compile time and the expression with which it's being called is not evaluated (more on this later).
How would this work on our example?
#include
void do_something() { std::cout << PRETTY_FUNCTION << "n"; }
void do_something(const char*) { std::cout << PRETTY_FUNCTION << "n"; }
int do_something(int) { std::cout << PRETTY_FUNCTION << "n"; return 123; }
template
auto wrap(Args... a) -> decltype( do_something(a...) ) {
std::cout << PRETTY_FUNCTION << "n";
return do_something(a...);
}
int main() {
wrap();
wrap("nice");
int x = wrap(42);
std::cout << x << "n";
return 0;
}
Try it (remember to add -std=c++0x) it works great! The syntax is not so terribly difficult to grasp as it was with variadic templates. The auto keywords says "hey, compiler, the return type for this method will be defined later", and then the -> actually declares the return type. This means that the auto-gt idiom isn't part of typedecl but a helper, which in turns means that even if not useful, this is valid C++0x code:
auto wrap() -> void {
}
This means that we have three interesting components to analyze in this scenario: * -> (delayed declaration) * auto * decltype
We'll go over each one the next time.
Closing remark: At first I choose the following example to introduce delayed return types and decltype (warning, untested code ahead):
#include
struct Foo {
void do_something() { std::cout << PRETTY_FUNCTION << "n"; }
void do_something(const char*) { std::cout << PRETTY_FUNCTION << "n"; }
int do_something(int) { std::cout << PRETTY_FUNCTION << "n"; return 123; }
};
// Untested code ahead
// This makes g++ coredump (v 4.4.5)
template
struct Wrap : public T {
template
auto wrap(Args... a) -> decltype( T::do_something(a...) ) {
std::cout << PRETTY_FUNCTION << "n";
return T::do_something(a...);
}
};
int main() {
Wrap w;
w.wrap();
w.wrap("nice");
std::cout << w.wrap(42) << "n";
return 0;
}
Though this looks MUCH better (and useful), at the time of writing this article mixing variadic templates with decltypes in a template class makes g++ segfault. It should be valid C++, but I can't assure it's correct code since I've never tried it.
Repeat (and fix) last command
Post by Nico Brailovsky @ 2011-05-26 | Permalink | Leave a comment
How many times have you run a command but forgot to add sudo at the beginning? How many times did you open vim instead of gvim? All that has an easy fix, instead of pressing up-left-left-left-left-left... (almost like a Konami code, isn't it?) just use !!
.
!!
expands to the previous command, so for example:
vim foo
, then
g!!
will execute "gvim foo".
Another common problem, you mistype vim for vmi (hey, it may be a common problem if you're dyslexic). Just type fc, short for fix command, to open the last command in your configured editor. Fix it (lxp, bonus points if anyone understand this :D) then write and save. The fixed command will be executed.
Cool C++0X features VII: A variadic wrapper solution
Post by Nico Brailovsky @ 2011-05-24 | Permalink | Leave a comment
Last time we were trying to build a wrapper function, in which we don't control the class being wrapped nor the user of the wrapper (meaning we can't change either of those but they could change without warning).
This was the first approach:
#include
void do_something() { std::cout << PRETTY_FUNCTION << "n"; }
void wrap() {
std::cout << PRETTY_FUNCTION << "n";
do_something();
}
int main() {
wrap();
return 0;
}
Yet, as we saw, it's not scalable, when either part changes the whole things break. We proposed then a variadic template solution, which, if you tried it yourself, should look something like this:
#include
void do_something() { std::cout << PRETTY_FUNCTION << "n"; }
void do_something(const char*) { std::cout << PRETTY_FUNCTION << "n"; }
template
void wrap(Args... a) {
std::cout << PRETTY_FUNCTION << "n";
do_something(a...);
}
int main() {
wrap();
wrap("nice");
return 0;
}
That's better. Now we don't care about which parameters do_something should get, nor how many of them are there supposed to be, just how it's called. If you read the previous entries on variadic templates this should be a walk in the park. It still has a flaw though: we need to know the return type of do_something!
Is there a way to write a wrapper without knowing the return type of a function you are wrapping? Yes, in Ruby you can. But now you can do it in C++0x too, and we'll see how to do it next time.
A closing remark: You could do something like this wrapping everything in a class:
#include
struct Foo {
void do_something() { std::cout << PRETTY_FUNCTION << "\n"; }
void do_something(const char*) { std::cout << PRETTY_FUNCTION << "\n"; }
};
template
struct Wrapper : public Base {
template
void wrap(Args... a) {
std::cout << PRETTY_FUNCTION << "n";
Base::do_something(a...);
}
};
int main() {
Wrapper w;
w.wrap();
w.wrap("nice");
return 0;
}
The above works just fine, but due to some limitations in the current (stable) version of gcc we will use the former version (the problem with this form will be clear later, I promise).
Another downgrade achieved
Post by Nico Brailovsky @ 2011-05-23 | Permalink | Leave a comment
Go home
Post by Nico Brailovsky @ 2011-05-19 | Permalink | 2 comments | Leave a comment
It really bothers me when people type "cd $HOME" or even worse, "cd /home/username". Why? Just type cd alone, it'll go home by itself.
Another useful cd tip, use "cd -" as an alias for "cd $OLDPWD" (oldpwd is the previous directory).
Cool C++0X features VI: A variadic wrapper
Post by Nico Brailovsky @ 2011-05-17 | Permalink | Leave a comment
Let's work on the last variadic exercise, a wrapper. Say you have something like this:
#include
void do_something() { std::cout << PRETTY_FUNCTION << "n"; }
int main() {
do_something();
return 0;
}
And you want to wrap do_something with something else (Remember __PRETTY_FUNCTION__?). This is a solution, the worst one though (or, to be accurate, the most boring one):
#include
void do_something() { std::cout << PRETTY_FUNCTION << "n"; }
void wrap() {
std::cout << PRETTY_FUNCTION << "n";
do_something();
}
int main() {
wrap();
return 0;
}
Why is it so bad? Let's say you don't control do_something, you just control the wrapper. You may not even control main(), it may be beyond your scope. That means each time do_something changes, or adds an overload, you have to change your code. That's ugly and you should already know how to set up a variadic function to forward the arguments to do_something. Give it a try, next time the solution.
Just to remind you
Post by Nico Brailovsky @ 2011-05-12 | Permalink | Leave a comment
It's been too long since the last time this image appeared on my blog:
Cool C++0X features V: Templates and angle brackets, a short interlude
Post by Nico Brailovsky @ 2011-05-10 | Permalink | Leave a comment
In the heart of C++ template metaprogramming and code obfuscation, lies the (ab)use of angle brackets. This seemingly innocent token can turn the most clean looking code into the mess that template-detractors like so much to complain about.
C++0x doesn't do much to clean up this mess, it's probably impossible, but it does offer a subtle feature to improve the legibility of C++ template code, a nifty little feature we have (inadvertently) used.
Up to C++0x, having two angle brackets together (>>) was parsed as the shift operator (like the one cout uses), meaning that if you had nested templates a lot of compiler errors ensued. C++0x corrects this, meaning that code which in C++ would be like this:
Reduce<Sum, Lst<Num<2>, Lst<Num<4>, Lst<Num<6>, Lst< Num<8> > > > > >
Can now be written like this:
Reduce<Sum, Lst<Num<2>, Lst<Num<4>, Lst<Num<6>, Lst< Num<8>>>>>>
Aaand, back to the normal schedule...
Eclipse watch expresion
Post by Nico Brailovsky @ 2011-05-05 | Permalink | Leave a comment
So, now that I'm working for the dark side: did you know Eclipse had watch expressions which shows a variable's value on real time? I bet you did, gdb has that too. Did you know a watch expression can evaluate a method call too? Neat, huh? Well, gdb has that too.
Anyway, someone on the team was having weird issues. A switch would jump to unexpected places. The state of an object would change between method calls. WTF?
After some debugging then it downed on me: I once (a long time before this strange behavior) saw this person using watch expressions to evaluate a method's return value. You now have enough information to troubleshoot this problem.
Ready? It's easy. A watch expression of a method call has the ability to alter an object's status. So, if you have something like this:
class Foo {
int a;
public:
Foo() : a(0) {}
void sumar(){ a++; }
};
int main() {
Foo bar;
/ do something /
return 42;
}
and then add a watch expression over bar.sumar(), then bar.a's value will be undefined for the execution of this program. Nice!
Cool C++0X features IV: Variadic templates again
Post by Nico Brailovsky @ 2011-05-03 | Permalink | 2 comments | Leave a comment
Last time we finally solved the varargs problem. Let's review what we learned: * Variadic templates let us create something receiving a variable set of arguments * We can process the head of that set, then recursively process the tail * It adds weird new syntax + When declaring typename... T you are saying "here goes a list of types" + When declaring T... t you are saying t is a list of objects with different type + When you write t..., you are saying "expand the list of arguments" * It's type safe * It's very neat to confuse your coworkers
So, what can we do with it besides implementing our own version of printf? Let's do something better, let's try adding up a list of numbers to start flexing our variadic templatefooness (?).
What's the usual way of adding a list of numbers? In templates, that is. We need something like this:
sum (H:T) <- H + sum(T)
sum () <- 0
Of course, in C++ templates you don't have values, you just have types. We could implement it like this (if this looks like a new language you may want to check my template metaprogramming series):
#include
struct Nil{};
template struct Lst {
typedef H Head;
typedef T Tail;
};
template <
template class Op,
typename Head,
typename Lst>
struct intForeach
{
typedef typename intForeach
< Op, typename Lst::Head, typename Lst::Tail >::result Next;
typedef typename Op< Head, Next >::result result;
};
template <
template class Op,
typename Head>
struct intForeach
{
typedef Head result;
};
template <
typename Lst,
template
class Op>
struct Reduce
{
typedef typename intForeach
< Op, typename Lst::Head, typename Lst::Tail >::result result;
};
template struct Num {
const static int value = N;
};
template struct Sum {
static const int r = A::value + B::value;
typedef Num result;
};
int main() {
std::cout << Reduce<
Lst<Num<2>, Lst<Num<4>, Lst<Num<6>, Lst< Num<8> > > > >,
Sum >::result::value << "n";
return 0;
}
Nothing too fancy, plain old recursion with a sum. Yet it's quite verbose, can we make this a little bit more terse and, hopefully, more clear? Yes, we can. Take a look at that Lst, Lst<...> It sucks. And it's the perfect place to use variadic templates, we just need to construct a structure getting a list of ints, like this:
template <
// The operation we wish to apply
template class Op,
// Current element to process
class H,
// All the rest
class... T>
struct Reduce_V
{
// TODO
}
That one should look familiar from last time article. Now, to implement a reduce operation we need to operate the current element with the result of reducing the tail, so we have to do something like this:
// Remember how T... means to expand T for the next instance
typedef typename Reduce_V::result Tail_Result
There's something missing. Can you see what? The ending condition, of course. Let's add it and we'll get something like this:
template <
// The operation we wish to apply
template class Op,
// All the rest
class... T>
struct Reduce_V
{
};
template <
// The operation we wish to apply
template class Op,
// All the rest
class H>
struct Reduce_V
{
typedef H result;
};
template <
// The operation we wish to apply
template class Op,
// Current element to process
class H,
// All the rest
class... T>
struct Reduce_V
{
// Remember how T… means to expand T for the next instance
typedef typename Reduce_V::result Tail_Result;
// Reduce current value with the next in line
typedef typename Op::result result;
};
And using it is very simple too:
std::cout << Reduce_V< Sum, Num<1>, Num<2>, Num<3>, Num<4>>::result::value << "n";
Next time we'll see another example for variadic templates and a new C++0x feature.