factor out a diagnostics helper for variadic templates
a nice offspring of this investigation
This commit is contained in:
parent
6fa8b41e1d
commit
4145452397
3 changed files with 182 additions and 15 deletions
|
|
@ -102,23 +102,15 @@ showRefRRefVal()
|
|||
: std::is_rvalue_reference<X>::value? " by MOVE": " VAL";
|
||||
}
|
||||
|
||||
template<typename X>
|
||||
template<typename... XS>
|
||||
void
|
||||
diagnostics (string id, X const& x)
|
||||
diagnostics (string id, XS const&... xs)
|
||||
{
|
||||
cout << "--"<<id<<"-- Type... " << lib::test::showType<X>()
|
||||
<< "\n Address ... " << &x
|
||||
<< showRefRRefVal<X>()
|
||||
cout << "--"<<id<<"--\n"
|
||||
<< lib::test::showVariadicTypes<XS...>(xs...)
|
||||
<< "\n"
|
||||
;
|
||||
}
|
||||
template<typename X, typename... XS>
|
||||
void
|
||||
diagnostics (string id, X const& x, XS const&... xs)
|
||||
{
|
||||
diagnostics<X> (id, x);
|
||||
diagnostics<XS...> (id, xs...);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@
|
|||
#include "lib/symbol.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
|
|
@ -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<typename R>
|
||||
string
|
||||
showRefKind()
|
||||
{
|
||||
return std::is_lvalue_reference<R>::value? "REF"
|
||||
: std::is_rvalue_reference<R>::value? "MOV"
|
||||
: "VAL";
|
||||
}
|
||||
|
||||
/** helper for investigating a variadic argument pack */
|
||||
inline string
|
||||
showVariadicTypes ()
|
||||
{
|
||||
return " :.";
|
||||
}
|
||||
|
||||
template<typename X, typename... XS>
|
||||
string
|
||||
showVariadicTypes (X const& x, XS const&... xs)
|
||||
{
|
||||
return " :---#"
|
||||
+ boost::lexical_cast<string>(1 + sizeof...(xs))
|
||||
+ " -- Type: " + showType<X>()
|
||||
+ " " + showRefKind<X>()
|
||||
+ " Address* " + boost::lexical_cast<string>(&x)
|
||||
+ "\n"
|
||||
+ showVariadicTypes (xs...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** create a random but not insane Time value */
|
||||
inline lib::time::Time
|
||||
randTime ()
|
||||
{
|
||||
|
|
|
|||
142
tests/library/test/test-helper-variadic-test.cpp
Normal file
142
tests/library/test/test-helper-variadic-test.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
TestHelperVariadic(Test) - verify variadic template diagnostics helper
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2014, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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 <boost/lexical_cast.hpp>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
//#include <map>
|
||||
|
||||
//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<double>(d) <<"\n";
|
||||
cout << "--reference--\n" << showVariadicTypes<double&>(d) <<"\n";
|
||||
cout << "--move--\n" << showVariadicTypes<double&&>(d) <<"\n";
|
||||
|
||||
forwardFunction("two values", "foo", 42L);
|
||||
forwardFunction("matched", d,dr,std::move(dr));
|
||||
|
||||
forwardFunction<Interface const&>("baseclass", ref);
|
||||
}
|
||||
|
||||
|
||||
template<typename... ARGS>
|
||||
void
|
||||
forwardFunction (string id, ARGS const&... args)
|
||||
{
|
||||
cout << "--"<<id<<"--\n"
|
||||
<< showVariadicTypes<ARGS...>(args...)
|
||||
<< "\n"
|
||||
;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (TestHelperVariadic_test, "unit common");
|
||||
|
||||
|
||||
}}} // namespace lib::test::test
|
||||
Loading…
Reference in a new issue