Showing posts with label workarounds. Show all posts
Showing posts with label workarounds. Show all posts

Tuesday, 17 January 2012

Nested lambda captures on Visual Studio

Are you using the 'new' lambda support in Visual Studio 2010? Of course you are, they're very useful. However, like some other parts of VC2010, they aren't without problems.

One of those problems is nested lambda captures. What I mean by that is capturing a variable which is itself captured. Imagine you have a matrix defined as follows:

typedef std::vector<int> row_t;
typedef std::vector<row_t> matrix_t;

If you wanted to, say, increment all elements of your matrix by a given value, you might do something like this:

void inc(matrix_t& m, int n)
{
    std::for_each(m.begin(), m.end(), [n](row_t& r) {
        std::for_each(r.begin(), r.end(), [n](int& e) {
            e += n;
        });
    });
}

Unfortunately, this gives the following error:

error C3480: '`anonymous-namespace'::<lambda0>::n': a lambda capture variable must be from an enclosing function scope

This appears to be a known problem. The workaround is to introduce a new variable inside your outer lambda and capture that instead:

void inc(matrix_t& m, int n)
{
    std::for_each(m.begin(), m.end(), [n](row_t& r) {
        int n2 = n;
        std::for_each(r.begin(), r.end(), [n2](int& e) {
            e += n2;
        });
    });
}

Happy lambdaing!

Friday, 30 December 2011

decltype on Visual Studio

Visual Studio 2010 had one of the first implementations of C++11's decltype. As such, it has some deficiencies.

One of the deficiencies occurs when you try to get the type of the address of a function template specialisation:

template <typename T>
void f();

decltype(&f<int>) ptr; // error - incorrect argument to 'decltype'

Like every programming problem, this can be worked around with an extra layer of indirection:

template <typename T>
T identity(T);

decltype(identity(&f<int>)) ptr; // ptr has type void(*)()

Hopefully this will be sufficient to get you by.

Monday, 26 December 2011

size_t

It bothers me that size_t, the result of sizeof, is in a header. Why should I have to pull in <stddef.h> or <cstddef> just to get the name of something which the compiler knows intrinsically?

Fortunately, C++11 provides a solution:

decltype(sizeof 0)

The expression in the sizeof is immaterial; I chose 0 because it was short and it already has special meaning in the language, so it doesn't look too out of place.