2008-01-27 23:40:45 +01:00
|
|
|
|
/*
|
2008-07-30 03:56:13 +02:00
|
|
|
|
Generator(Test) - build an interface + implementation directed by a typelis
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2008, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
**Lumiera** 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. See the file COPYING for further details.
|
2010-12-10 02:55:40 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
* *****************************************************************/
|
2008-01-27 23:40:45 +01:00
|
|
|
|
|
|
|
|
|
|
|
2009-06-20 01:28:47 +02:00
|
|
|
|
/** @file generator-test.cpp
|
2008-02-06 05:34:19 +01:00
|
|
|
|
** \par what are we doing here??
|
2010-12-17 22:51:27 +01:00
|
|
|
|
**
|
2008-02-06 05:34:19 +01:00
|
|
|
|
** the following test composes both an interface and the corresponding implementation
|
|
|
|
|
|
** by instantiating "building block" templates over a collection of types. The resulting
|
2010-12-10 02:55:40 +01:00
|
|
|
|
** class ends up inheriting a \e virtual function instantiated for each of the types
|
2008-02-06 05:34:19 +01:00
|
|
|
|
** in the list. (remember: normally the number and signature of all virtual functions
|
|
|
|
|
|
** need to be absolutely fixed in the class definition)
|
2010-12-17 22:51:27 +01:00
|
|
|
|
**
|
2009-06-20 01:28:47 +02:00
|
|
|
|
** @see typelist-test.cpp
|
2008-07-30 03:56:13 +02:00
|
|
|
|
** @see generator.hpp
|
2008-03-10 08:38:59 +01:00
|
|
|
|
** @see lumiera::query::ConfigRules a real world usage example
|
2008-02-06 05:34:19 +01:00
|
|
|
|
**
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-18 04:47:41 +01:00
|
|
|
|
#include "lib/test/run.hpp"
|
2013-09-01 17:36:05 +02:00
|
|
|
|
#include "lib/format-string.hpp"
|
2008-12-18 04:47:41 +01:00
|
|
|
|
#include "lib/meta/generator.hpp"
|
2008-01-27 23:40:45 +01:00
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
2013-09-01 17:36:05 +02:00
|
|
|
|
#include <string>
|
2008-01-27 23:40:45 +01:00
|
|
|
|
|
2014-09-25 02:50:02 +02:00
|
|
|
|
using util::_Fmt;
|
2008-01-27 23:40:45 +01:00
|
|
|
|
using std::string;
|
|
|
|
|
|
using std::cout;
|
|
|
|
|
|
|
Upgrade: address warnings -- shaddowing overloaded-virtual
This is an advanced diagnostics added (presumably) with GCC-13
and attempts to protect against an insidious side-effect of ''overload resolution''
Basically C++ (like its ancestor C) is oriented towards direct linkage and adds
the OO-style dynamic dispatch (through virtual functions and a VTable)
only as an extension, which must be requested explicitly.
Thus the resolution of ''overloads'' (as opposed to ''overridden'' virtual functions)
always takes precedence and happens within the directly visible scope,
which can cause the compiler to perform an implicit conversion instead of
invoking a different virtual function, which is defined in a base class.
However, this diagnostics seems to be implemented in an overly zealous way:
The compiler warns at the time of the type instantiation, and even in cases
where it is effectively impossible to encounter this dangerous shadowing situation.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109740
This leads to several ill-guided warnings in the Lumiera code base, which unfortunately
can only be addressed by disabling this diagnostics for all usages of some header.
The reason is, we often generate chains of template instantiations driven by type lists,
and in such usage pattern, it is not even possible to bring all the other inherited overloads
into scope (with a using `BASE::func` clause), because such a specification would be ambiguous
and result in a real compile error, because even the interface is generated from a chain of mix-in templates
2025-04-15 22:42:34 +02:00
|
|
|
|
// GCC > 13 warns at class definition when a new overload shadows an inherited virtual function.
|
|
|
|
|
|
// While theoretically correct, this warning is besides the point when an interface is assembled
|
|
|
|
|
|
// by metaprogramming from a chain of template instantiations, driven by a type list
|
|
|
|
|
|
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109740
|
|
|
|
|
|
_Pragma("GCC diagnostic push") \
|
|
|
|
|
|
_Pragma("GCC diagnostic ignored \"-Woverloaded-virtual\"")
|
|
|
|
|
|
|
2008-01-27 23:40:45 +01:00
|
|
|
|
|
2011-12-03 02:56:50 +01:00
|
|
|
|
namespace lib {
|
|
|
|
|
|
namespace meta {
|
2009-06-20 01:28:47 +02:00
|
|
|
|
namespace test {
|
2010-12-17 22:51:27 +01:00
|
|
|
|
|
|
|
|
|
|
/** template for generating lots of different test types */
|
|
|
|
|
|
template<int I>
|
|
|
|
|
|
struct Block
|
|
|
|
|
|
{
|
|
|
|
|
|
static string name;
|
|
|
|
|
|
string talk() { return "__"+name+"__"; }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<int I>
|
2014-09-25 02:50:02 +02:00
|
|
|
|
string Block<I>::name = _Fmt("Block<%2i>") % I;
|
2010-12-17 22:51:27 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Use this building block for assembling an abstract interface */
|
|
|
|
|
|
template<class X>
|
|
|
|
|
|
class TakeIt
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual void eat (X& x) = 0;
|
|
|
|
|
|
virtual ~TakeIt() { }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** Use this building block for chaining corresponding implementation classes. */
|
|
|
|
|
|
template<class X, class BASE>
|
|
|
|
|
|
class DoIt
|
|
|
|
|
|
: public BASE
|
|
|
|
|
|
{
|
|
|
|
|
|
protected:
|
|
|
|
|
|
DoIt () { cout << "ctor DoIt<"<< X::name << " >\n";}
|
|
|
|
|
|
virtual ~DoIt() { cout << "dtor DoIt<"<< X::name << " >\n";}
|
|
|
|
|
|
public:
|
|
|
|
|
|
void eat (X& x) { cout << "devouring" << x.talk() << "\n";}
|
|
|
|
|
|
using BASE::eat; // prevent shadowing
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-06-02 02:24:09 +02:00
|
|
|
|
typedef TyOLD< Block<1>
|
2010-12-17 22:51:27 +01:00
|
|
|
|
, Block<2>
|
|
|
|
|
|
, Block<3>
|
|
|
|
|
|
, Block<5>
|
|
|
|
|
|
, Block<8>
|
|
|
|
|
|
, Block<13>
|
|
|
|
|
|
>::List TheTypes;
|
|
|
|
|
|
|
|
|
|
|
|
typedef InstantiateForEach<TheTypes,TakeIt> TheInterface;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct BaseImpl : public TheInterface
|
|
|
|
|
|
{
|
|
|
|
|
|
void eat() { cout << "gulp!\n"; }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef InstantiateChained<TheTypes,DoIt, BaseImpl> NumberBabbler;
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-24 23:06:36 +02:00
|
|
|
|
/*********************************************************************//**
|
2010-12-17 22:51:27 +01:00
|
|
|
|
* @test check the helpers for dealing with lists-of-types.
|
|
|
|
|
|
* Build an interface and an implementation class
|
|
|
|
|
|
* by inheriting template instantiations
|
|
|
|
|
|
* for a collection of classes</li>
|
|
|
|
|
|
*/
|
|
|
|
|
|
class TypeListGenerator_test : public Test
|
|
|
|
|
|
{
|
2015-04-20 03:41:28 +02:00
|
|
|
|
virtual void
|
|
|
|
|
|
run (Arg)
|
2008-01-27 23:40:45 +01:00
|
|
|
|
{
|
2010-12-17 22:51:27 +01:00
|
|
|
|
NumberBabbler me_can_has_more_numberz;
|
|
|
|
|
|
|
|
|
|
|
|
CHECK (INSTANCEOF (TheInterface, &me_can_has_more_numberz));
|
|
|
|
|
|
|
|
|
|
|
|
TheTypes::Tail::Head b2; // Block<2>
|
|
|
|
|
|
TheTypes::Tail::Tail::Tail::Head b5; // Block<5>
|
|
|
|
|
|
TheTypes::Tail::Tail::Tail::Tail::Tail::Head b13; // Block<13>
|
|
|
|
|
|
|
|
|
|
|
|
me_can_has_more_numberz.eat (b2);
|
|
|
|
|
|
me_can_has_more_numberz.eat (b5);
|
|
|
|
|
|
|
2016-12-23 04:23:03 +01:00
|
|
|
|
TakeIt<Block<13>>& subInterface = me_can_has_more_numberz;
|
2010-12-17 22:51:27 +01:00
|
|
|
|
|
|
|
|
|
|
subInterface.eat (b13);
|
|
|
|
|
|
me_can_has_more_numberz.eat();
|
|
|
|
|
|
|
2011-12-19 03:02:48 +01:00
|
|
|
|
INFO (test, "SizeOf = %zu", sizeof(me_can_has_more_numberz));
|
2010-12-17 22:51:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Register this test class... */
|
|
|
|
|
|
LAUNCHER (TypeListGenerator_test, "unit common");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-03 02:56:50 +01:00
|
|
|
|
}}} // namespace lib::meta::test
|