Generic Lambdas in C++ using Clang

An Implementation of generic (polymorphic) lambdas using clang (llvm version 167560 [11/7/12]); based on C++ Portland October 2012 meeting

View the Project on GitHub faisalv/clang-glambda

Generic Lambdas in C++ using Clang

This is a Toy implementation of Generic Lambdas for C++ based on the n3418: Proposal for Generic Lambda Expressions.

This is NOT by any means intended to be a production ready implementation, and almost certainly has bugs that either I have not yet discovered, or bugs that have been reported (thank you in advance for making the effort to do so) and which I am currently working on. Please visit Scott Prager's tests for further information on code it can compile.

This implementation's raison d'ĂȘtre is to encourage developers to play with the generic lambda feature and provide bug reports and feedback to us. We hope that this will prove useful to the C++ community and help guide us as we work on the next version of our proposal for the C++ Standardization meeting to be held in Bristol (April 2013).

The current version (12/2012) implements subproposals 2.1, 2.2, 2.3 and 2.5.

2.1 Allow the type-specifier within a parameter declaration of a lambda to be auto (i.e. auto is mandatory)

auto Sum = [](auto a, decltype(a) b) { return a + b; };
int i = Sum(3, 4);
double d = Sum(3.14, 2.77);

2.2 Allow the use of familiar template syntax in lambda expressions

auto NumElements = []<int N>(auto (&a)[N]) { return N; }; 
int arri[]{1, 2, 3};
double arrd[]{3.14, 2.77, 6.626};
auto total = NumElements(arri) + NumElements(arrd);

2.3 Permit a lambda body to be an expression

int local = 10;
auto L = [&](auto a) a + ++local;

2.4 Named Lambda Syntax has NOT been implemented yet

2.5 Autogenerate a conversion to function pointer in captureless generic lambdas

auto L = [](auto a, decltype(a) b) { return a + b; };
int (*fp)(int, int) = L;

I also used Richard Smith's (@zygoloid) return type deduction patch to allow the following

int local = 10;
auto L = [](auto &a) -> auto& { return a; };
++L(local); 

How to Compile the Code on Windows

  1. Checkout the appropriate version of llvm (167560) by following the instructions at : http://clang.llvm.org/get_started.html. I use TortoiseSVN on windows. Be sure to download the correct version of llvm (167560) (use the -r option on command line). Do NOT checkout anything else (i.e compiler-RT etc.) except for the correct revision of the llvm snapshot.
  2. In the above instructions from the clang website, where it states to checkout clang using subversion (i.e step 3 svn co http://llvm.org/svn/llvm-project/cfe/trunk clang), instead install git (I use TortoiseGit on windows) and clone this repository into the subdirectory clang. For e.g, using the command line when in your-dir/llvm/tools/ try:
    git clone git:/github.com/faisalv/clang-glambda.git clang
    
  3. Then follow the instructions as delineated on clangs website to compile and build clang.
  4. Keep in mind that all the development has been done using Visual Studio 2010.
  5. Once you have your clang binary, it should be able to compile your code, but on windows, I find myself having to use the interpreter lli.exe to actually execute my clang "compiled" code. So I do the following when trying to compile code in test.cpp:
    clang -std=c++1y -c test.cpp -emit-llvm -o test.bc
    lli test.bc
    

How to use the Windows binaries:

  1. I have uploaded my most recent Debug build of generic-lambda-clang that was built using visual studio 2010.
  2. In order for you to use it, you need certain debug dlls that I can not legally post here - An easy way is probably for you to install Visual C++ 2010 Express (free).
  3. Download the windows executable generic-lambda-clang.exe along with the llvm interpreter: lli.exe if you need it.
    generic-lambda-clang -std=c++1y -c test.cpp -emit-llvm -o test.bc
    lli test.bc
    
  4. FYI: lli does cause bugs with executing the following code: (This appears to be a bug with lli.exe and last I checked also occurred with the actual clang snapshot and has nothing to do with my changes). The bug does not occur if you are on a platform that can compile the code natively.
    template < class F1, class F2>
    struct overload : F1, F2 {
    overload(F1 const& f1, F2 const& f2)
    : F1(f1), F2(f2) { }
    using F1::operator();
    using F2::operator();
    };
    template <class F1, class F2>
    overload <F1, F2> make_overload(F1 const& f1, F2 const& f2) {
    return overload <F1, F2>(f1, f2);
    }
    int main() {
    auto f1 = & { return i; }; 
    auto f2 = & { return 0; };
    auto f = make_overload(f1, f2);
    printf("%d\n", f(5));
    printf("%d\n", f(3.14));
    }
    

How to Compile the code on MacOS Lion

  1. Download and install XCode
  2. Checkout the appropriate version of llvm (167560) by following the instructions at Clang's Website. Try this:
    svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm -r 167560
    
    Do NOT checkout anything else (i.e compiler-RT etc.) except for the correct revision of the llvm snapshot.
  3. In the above instructions from the clang website, where it states to checkout clang using subversion (i.e step 3 svn co http://llvm.org/svn/llvm-project/cfe/trunk clang), instead install git and clone this repository into the subdirectory clang. For e.g, using the command line when in your-dir/llvm/tools/ try:
    git clone git:/github.com/faisalv/clang-glambda.git clang
    
  4. Then follow the instructions as delineated on clangs website to compile and build clang.
  5. Once you have your clang binary, it should be able to compile your code into an executable. The binary typically gets dumped in build/Debug&Asserts/bin/.
    ./clang -std=c++1y test.cpp
    ./a.out
    
  6. Please let me know if you encounter any bugs with any part of the process.

How to use the MacOS Lion Binaries

  1. Download generic-lambda-clang-lion
  2. Try the following:
    ./generic-lambda-clang-lion test.cpp -std=c++1y
    ./a.out
    
  3. Please Let me know if it works for you (I have been unable to test it on a non-development box)