* tests/data/transform-lambda.cc: New.
* tests/data/Makefile.am (EXTRA_PROGRAMS)
(transform_lambda_SOURCES): New.
(extra-check): New (phony) target.
---
milena/ChangeLog | 9 +++
milena/tests/data/Makefile.am | 12 +++
milena/tests/data/transform-lambda.cc | 123 +++++++++++++++++++++++++++++++++
3 files changed, 144 insertions(+), 0 deletions(-)
create mode 100644 milena/tests/data/transform-lambda.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 5712ee9..65f6803 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,12 @@
+2012-05-22 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Add an optional test to exercise mln::transform with lambdas.
+
+ * tests/data/transform-lambda.cc: New.
+ * tests/data/Makefile.am (EXTRA_PROGRAMS)
+ (transform_lambda_SOURCES): New.
+ (extra-check): New (phony) target.
+
2011-09-15 Guillaume Lazzara <z(a)lrde.epita.fr>
Fix Scribo build system.
diff --git a/milena/tests/data/Makefile.am b/milena/tests/data/Makefile.am
index 205337e..269567b 100644
--- a/milena/tests/data/Makefile.am
+++ b/milena/tests/data/Makefile.am
@@ -74,3 +74,15 @@ MOSTLYCLEANFILES = \
median-out_line.pgm \
median-out_rect.pgm \
median_fast-out.pgm
+
+
+# FIXME: We should introduce a conditional (e.g named HAVE_CXX_LAMBDA)
+# to guard these lines, and make them actually part of the test suite
+# if the C++ compiler found by `configure' supports lambda
+# abstractions.
+EXTRA_PROGRAMS = transform-lambda
+transform_lambda_SOURCES = transform-lambda.cc
+
+.PHONY: extra-check
+extra-check: transform-lambda
+ ./transform-lambda$(EXEEXT)
diff --git a/milena/tests/data/transform-lambda.cc
b/milena/tests/data/transform-lambda.cc
new file mode 100644
index 0000000..25de53a
--- /dev/null
+++ b/milena/tests/data/transform-lambda.cc
@@ -0,0 +1,123 @@
+// Copyright (C) 2012 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+/// \file
+/// Exercise mln::data::transform with a lambda abstraction.
+
+#include <type_traits>
+
+#include <mln/core/concept/function.hh>
+#include <mln/fun/c.hh>
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/data/transform.hh>
+#include <mln/debug/iota.hh>
+#include <mln/debug/println.hh>
+
+
+/*----------------.
+| Lambda traits. |
+`----------------*/
+
+// Metaprogramming traits for the deduction of return and argument
+// types of lambda asbtractions. Inspired from
+//
http://stackoverflow.com/questions/6512019/can-we-get-the-type-of-a-lambda-…
+
+/// Deduce the type of \p F's first argument.
+template <typename F>
+struct first_arg_of
+{
+ template <typename Ret, typename A, typename... Rest>
+ static A
+ helper(Ret (F::*)(A, Rest...));
+
+ template <typename Ret, typename A, typename... Rest>
+ static A
+ helper(Ret (F::*)(A, Rest...) const);
+
+ typedef decltype( helper(&F::operator()) ) type;
+};
+
+/// Deduce the type of \p F's first argument.
+///
+/// This traits works with lambdas, whereas std::result_of does not.
+template <typename F>
+struct return_of
+{
+ template <typename Ret, typename A, typename... Rest>
+ static Ret
+ helper(Ret (F::*)(A, Rest...));
+
+ template <typename Ret, typename A, typename... Rest>
+ static Ret
+ helper(Ret (F::*)(A, Rest...) const);
+
+ typedef decltype( helper(&F::operator()) ) type;
+};
+
+
+/*---------------------.
+| Conversion routine. |
+`---------------------*/
+
+/// Convert a lambda abstraction into a Milena function (functor).
+
+template <typename F>
+auto
+to_fun (F f) -> mln::fun::C< typename return_of<F>::type (*) (typename
first_arg_of<F>::type) >
+{
+ return mln::fun::C< typename return_of<F>::type (*) (typename
first_arg_of<F>::type) > (f);
+}
+
+
+/*-------.
+| Test. |
+`-------*/
+
+int
+main()
+{
+ using namespace mln;
+
+ // FIXME: Replacing unsigned by int_u8 would trigger a bug here, as
+ // the (low quantization) implementation of data::transform would
+ // create values that would not fit in int_u8 (e.g. sqr(16) = 256).
+ typedef unsigned V;
+ typedef image2d<V> I;
+
+ I input(3, 3);
+ debug::iota(input);
+
+ auto sqr = [](V x) { return x * x; };
+
+ I output = data::transform(input, to_fun([](V x) { return x * x; }));
+ debug::println(output);
+
+ // FIXME: Or use mln::test instead?
+ mln_piter_(I) p(output.domain());
+ for_all(p)
+ mln_assertion(output(p) = math::sqr(input(p)));
+}
--
1.7.2.5