Welcome to part 2 of my ramblings about C++11. Note that all of these posts are in the C++11 category, so it is easy to go an read previous entries. This post is going to focus on a new syntax for declaring the return type of functions.
Lets go back to the example of calculating a dot product of two vectors given in the first post of this series:
template<class T, class U>
void dot_product(const vector<T> vt, const vector<U> vu)
Once it is calculated, we probably want to actually return the value! However, we do not know the type of the output. Using decltype seems the way to go. For example:
template<class T, class U>
decltype(vt[0] * vu[0]) dot_product(const vector<T> vt, const vector<U> vu);
However, there is an issue here… And it is not the fact that vt[0] might not exist if you provide a zero length vector, as that does not matter (I guess because the return type of the [] operator is known). Nor is it that the result might overflow the type of an individual multiplication – stop being picky about fake code! The issue is that we do not know what vt and vu are at that stage of the function declaration. You could use:
decltype(*(T*)(0)**(U*)(0))
but the less said about that the better… This is where a new (optional) function declaration syntax comes into play:
template<class T, class U>
auto dot_product(const vector<T> vt, const vector<U> vu) -> decltype(vt[0] * vu[0]);
Although useful for templates, this syntax is really about scope. For example, consider:
class Foo
{
public:
enum Bar { FOO, BAR, BAZ };
Bar getBar();
private:
Bar bar;
};
When defining the function getBar(), the following is wrong:
Bar Foo::getBar() { /* ... */ }
as Bar is out of scope – at that stage we do not know we are in a method for the Foo class. That can be easily fixed in this case by using Foo::Bar as the return type, but that can get messy in more complex cases. Better to use:
auto Foo::getBar() -> Bar { /* ... */ }
Then by the time Bar is reached, we know we are in the scope of the Foo class.