diff --git a/research/try.cpp b/research/try.cpp index 26a3d595a..400e6d74b 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -102,23 +102,15 @@ showRefRRefVal() : std::is_rvalue_reference::value? " by MOVE": " VAL"; } -template +template void -diagnostics (string id, X const& x) +diagnostics (string id, XS const&... xs) { - cout << "--"<() - << "\n Address ... " << &x - << showRefRRefVal() + cout << "--"<(xs...) << "\n" ; } -template -void -diagnostics (string id, X const& x, XS const&... xs) -{ - diagnostics (id, x); - diagnostics (id, xs...); -} void diff --git a/src/lib/test/test-helper.hpp b/src/lib/test/test-helper.hpp index 8a778840f..3d0332c3f 100644 --- a/src/lib/test/test-helper.hpp +++ b/src/lib/test/test-helper.hpp @@ -28,9 +28,10 @@ #include "lib/symbol.hpp" #include "lib/time/timevalue.hpp" +#include #include -#include #include +#include @@ -101,8 +102,40 @@ namespace test{ - - /** create a random but not insane Time value */ + /** helper to discern the kind of reference of the argument type */ + template + string + showRefKind() + { + return std::is_lvalue_reference::value? "REF" + : std::is_rvalue_reference::value? "MOV" + : "VAL"; + } + + /** helper for investigating a variadic argument pack */ + inline string + showVariadicTypes () + { + return " :."; + } + + template + string + showVariadicTypes (X const& x, XS const&... xs) + { + return " :---#" + + boost::lexical_cast(1 + sizeof...(xs)) + + " -- Type: " + showType() + + " " + showRefKind() + + " Address* " + boost::lexical_cast(&x) + + "\n" + + showVariadicTypes (xs...); + } + + + + + /** create a random but not insane Time value */ inline lib::time::Time randTime () { diff --git a/tests/library/test/test-helper-variadic-test.cpp b/tests/library/test/test-helper-variadic-test.cpp new file mode 100644 index 000000000..d171dcf4c --- /dev/null +++ b/tests/library/test/test-helper-variadic-test.cpp @@ -0,0 +1,142 @@ +/* + TestHelperVariadic(Test) - verify variadic template diagnostics helper + + Copyright (C) Lumiera.org + 2014, Hermann Vosseler + + This program 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; either version 2 of + the License, or (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "lib/test/test-helper.hpp" +//#include "lib/util.hpp" + + +//#include +#include +#include +#include +#include +//#include + +//using boost::lexical_cast; +//using util::contains; +using std::string; +using std::cout; +//using std::endl; + + +namespace lib { +namespace test{ +namespace test{ + + namespace { // test fixture... + + class Interface + { + public: + Interface(){} + Interface(Interface const& o) { cout << "COPY.CT from "<<&o<<" !!!\n"; } + Interface(Interface const&& o) { cout << "MOVE.CT from "<<&o<<" !!!\n"; } + + Interface& operator= (Interface const& o) { cout << "COPY= from "<<&o<<" !!!\n"; return *this; } + Interface& operator= (Interface const&& o) { cout << "MOVE= from "<<&o<<" !!!\n"; return *this; } + + virtual ~Interface() { } + }; + + class Impl + : public Interface + { + string s_; + + public: + Impl(string ss ="IMP") : s_(ss) { } + }; + + + inline double + makeRvalue() + { + return atan2(0,-0.0); + } + + + }//(End) test fixture + + + + + + + /****************************************************************************//** + * @test document usage of the diagnostics helper for variadic templates. + * Errors in variadic template instantiations are sometimes hard to spot, + * due to the intricacies of template argument matching and the + * reference collapsing rules. Our diagnostics facility is itself a + * variadic function template, which, when supplied with an argument pack, + * will build a diagnostic string describing the arguments. + * @warning care has to be taken to pass the template arguments properly, + * since template argument matching might mess up the reference kind + * (rvalue, lvalue) of the passed types. Thus, either use std::forward, + * or spell out the template argument(s) explicitly on invocation + * + * @see showVariadicTypes() + * @see TestHelper_test + */ + class TestHelperVariadic_test : public Test + { + + virtual void + run (Arg) + { + double d = makeRvalue(); + double& dr = d; + + Impl obj; + Interface const& ref = obj; + + cout << "--no-arg--\n" << showVariadicTypes() <<"\n"; + cout << "--value--\n" << showVariadicTypes(d) <<"\n"; + cout << "--reference--\n" << showVariadicTypes(d) <<"\n"; + cout << "--move--\n" << showVariadicTypes(d) <<"\n"; + + forwardFunction("two values", "foo", 42L); + forwardFunction("matched", d,dr,std::move(dr)); + + forwardFunction("baseclass", ref); + } + + + template + void + forwardFunction (string id, ARGS const&... args) + { + cout << "--"<(args...) + << "\n" + ; + } + + }; + + + /** Register this test class... */ + LAUNCHER (TestHelperVariadic_test, "unit common"); + + +}}} // namespace lib::test::test