pax_global_header00006660000000000000000000000064130254671700014517gustar00rootroot0000000000000052 comment=5ef0edbaeefb59f8ae5d787eb9a261a496a05693 dune-typetree-2.5.0/000077500000000000000000000000001302546717000143155ustar00rootroot00000000000000dune-typetree-2.5.0/.gitignore000066400000000000000000000006701302546717000163100ustar00rootroot00000000000000# build artefacts strewn throughout the tree .libs/ .deps/ *.o *.lo *.a *.la Makefile Makefile.in # specific files created by the build system in the module root /aclocal.m4 /am /autom4te.cache /build-cmake /config.guess /config.h /config.h.in /config.log /config.lt /config.status /config.sub /configure /configure.lineno /depcomp /dependencies.m4 /dune-typetree.pc /install-sh /libtool /ltmain.sh /missing /stamp-h1 /test-driver compile dune-typetree-2.5.0/.gitlab-ci.yml000066400000000000000000000012501302546717000167470ustar00rootroot00000000000000--- variables: DUNECI_BRANCH: releases/2.5 before_script: - duneci-install-module https://gitlab.dune-project.org/core/dune-common.git debian:9--gcc: image: duneci/base:9 script: duneci-standard-test debian:9--clang: image: duneci/base:9 script: duneci-standard-test --opts=/duneci/opts.clang debian:8--gcc: image: duneci/base:8 script: duneci-standard-test debian:8-backports--clang: image: duneci/base:8-backports script: duneci-standard-test --opts=/duneci/opts.clang ubuntu:16.04--gcc: image: duneci/base:16.04 script: duneci-standard-test ubuntu:16.04--clang: image: duneci/base:16.04 script: duneci-standard-test --opts=/duneci/opts.clang dune-typetree-2.5.0/CHANGELOG.md000066400000000000000000000063251302546717000161340ustar00rootroot00000000000000TypeTree ======== This is the 2.4.0-rc1 version of the TypeTree library for statically typed object trees. TypeTree 2.4.0-rc1 is compatible with the 2.4.0 release of the DUNE core modules and the 2.4.0 release of PDELab. Changes ======= TypeTree 2.5 ------------ - TypeTree has updated its minimum compiler requirements. You now need a compiler that is at least compatible with GCC 4.9 in C++14 mode. - Removed support for Autotools. TypeTree 2.4 ------------ - TypeTree has updated its minimum compiler requirements. You now need a compiler that is at least compatible with GCC 4.7 in C++11 mode. - A lot of compatibility code for older compilers has been removed. In particular, the old CompositeNode with a fixed number of children has been removed and the old VariadicCompositeNode has been renamed to CompositeNode. - As part of these changes, we were able to remove libdunetypetree, so TypeTree is now a header-only library. Thanks, Ansgar! - In addition to the `DynamicTreePath` and the fully static `TreePath`, there is now a `HybridTreePath`, which allows users to use a runtime index in some places of the path and a compile time index at others. - As part of this new `HybridTreePath`, there is a backport of the C++14 index_sequence to C++11 in the namespace `Dune::TypeTree::Std`. Moreover, there is an `index_constant`, which is an alias template for `std::integral_constant`, and a number of predefined `constexpr` objects `Dune::TypeTree::Indices::_0` etc, which are just `index_constant`s of the specified value. These exist up to the index 19 for now. - Based on the new `HybridTreePath` and those `index_constant`s, there is now a much more user-friendly way of extracting child nodes: All interior nodes now have a method `child()` which accepts either - a sequence of integers and `index_constant`s - a `HybridTreePath` - a `TreePath` and returns the subtree rooted at that path. There is also a freestanding function `child(node,path)`, which should be used in generic algorithm code as it is more robust (it can e.g. deal correctly with an empty path). - The old child extraction using `extract_child()` has been deprecated. - Lots of smaller fixes - Release history - TypeTree 2.4.0 - Fix rendering of links in README - TypeTree 2.4.0-rc1 - Initial release candidate TypeTree 2.3 ------------ This release only contains minor changes to fix buildsystem issues and fix a number of bugs. - Full support for CMake (thanks to Christoph and Markus!). - Fixes to Autotools tests. - Resolved some compilation problems on older compilers. - Release history TypeTree 2.3.1 - Release without further changes TypeTree 2.3.1-rc1 - Small fixes to included headers and documentation TypeTree 2.3.0 - Skipped because version 2.3.1 of the core modules was released in the meantime and it was considered better to keep the version numbers in sync TypeTree 1.0 ------------ This is the initial standalone release. It only contains changes due to the extraction from the PDELab sources. - Moved headers from dune/pdelab/common/typetree/ to dune/typetree/. - Changed namespace from Dune::PDELab::TypeTree to Dune::TypeTree. - Moved tests to top-level directory tests/. dune-typetree-2.5.0/CMakeLists.txt000066400000000000000000000014641302546717000170620ustar00rootroot00000000000000# set up project project("dune-typetree" C CXX) # general stuff cmake_minimum_required(VERSION 2.8.6) if(NOT (dune-common_DIR OR dune-common_ROOT OR "${CMAKE_PREFIX_PATH}" MATCHES ".*dune-common.*")) string(REPLACE ${CMAKE_PROJECT_NAME} dune-common dune-common_DIR ${PROJECT_BINARY_DIR}) endif() #find dune-common and set the module path find_package(dune-common REQUIRED) list(APPEND CMAKE_MODULE_PATH ${dune-common_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/modules") #include the dune macros include(DuneMacros) # start a dune project with information from dune.module dune_project() add_subdirectory(cmake/modules) add_subdirectory(doc) add_subdirectory(dune) add_subdirectory(test) # finalize the dune project, e.g. generating config.h etc. finalize_dune_project(GENERATE_CONFIG_H_CMAKE) dune-typetree-2.5.0/COPYING000077700000000000000000000000001302546717000167472LICENSE.mdustar00rootroot00000000000000dune-typetree-2.5.0/GPL-2000066400000000000000000000432541302546717000150310ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. dune-typetree-2.5.0/GPL-3000066400000000000000000001045131302546717000150260ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . dune-typetree-2.5.0/LGPL-3000066400000000000000000000167431302546717000151510ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. dune-typetree-2.5.0/LICENSE.md000066400000000000000000000050051302546717000157210ustar00rootroot00000000000000Licensing Information ===================== Copyright holders ----------------- | Year | Name | |------------|----------------------------| | 2009 | Peter Bastian | | 2009--2014 | Markus Blatt | | 2013 | Andreas Buhr | | 2014--2016 | Ansgar Burchardt | | 2009--2016 | Christian Engwer | | 2009--2013 | Jorrit Fahlke | | 2015--2016 | Carsten Gräser | | 2015--2016 | Felix Gruber | | 2013--2016 | Christoph Grüninger | | 2013--2016 | Dominic Kempf | | 2010--2016 | Steffen Müthing | | 2012 | Rebecca Neumann | | 2015 | Elias Pipping | | 2015 | Oliver Sander | | 2013 | Bård Skaflestad | License ------- The TypeTree library, headers and test programs are copyrighted free software. You can use, modify and/or redistribute it under the terms of either one of the two following licenses: * The GNU Lesser General Public License as published by the Free Software Foundation, either Version 3 of the license or (at your option) any later version. You can find a copy of the GNU Lesser General Public License, Version 3, in the files [GPL-3][1] and [LGPL-3][2] or at http://www.gnu.org/licenses/lgpl-3.0. * Version 2 of the GNU General Public License as published by the Free Software Foundation, with the following special exception for linking and compiling against the TypeTree library, the so-called "runtime exception": > As a special exception, you may use the PDELab source files as part of a > software library or application without restriction. Specifically, if other > files instantiate templates or use macros or inline functions from one or > more of the PDELab source files, or you compile one or more of the PDELab > source files and link them with other files to produce an executable, this > 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. This license is intended to be similar to the GNU Lesser General Public License, Version 2, which by itself isn't suitable for a template library. You can find a copy of the GNU General Public License, Version 2, in the file [GPL-2][3] or at http://www.gnu.org/licenses/gpl-2.0. Links ----- [1]: GPL-3 [2]: LGPL-3 [3]: GPL-2 dune-typetree-2.5.0/README.md000066400000000000000000000070711302546717000156010ustar00rootroot00000000000000TypeTree ======== This is version 2.4.0-rc1 of the TypeTree library. TypeTree is a template library for constructing and operating on statically typed trees of objects. It is based around the idea of defining loosely coupled, componentized algorithms. Component lookup happens through tag dispatch, making it very easy to extend and / or modify existing algorithms as well as constructing new algorithms for existing types of tree nodes. The provided algorithms include visitor-based iteration of both single trees and pairs of trees and a powerful tree transformation algorithm that automatically decomposes an existing tree and constructs the transformed one, only requiring the user to specify the per-node transformation policies. Moreover, there are some more specialized utility algorithms for compile-time reductions over trees and leaves, which are mainly useful for the construction of template meta programs. Finally, there are mixin implementations of the three default node concepts in the library (leaf nodes, power nodes and composite nodes). For more complicated use patterns, the library also contains generic implementations of proxy nodes and, on top of that functionality, filtered nodes that can reorder and / or restrict access to some of their children. The TypeTree library was originally developed as part of [PDELab][0] to support its tree-based abstraction of function spaces, but has attracted wider-spread interest. To facility integration with other projects, we have extracted the code from PDELab into this standalone library This package contains the TypeTree library code. For usage examples your best bet is to look at the PDELab package. If you have downloaded a release tarball, you can find the autogenerated Doxygen API documentation in doc/doxygen/html. Otherwise, you can build this documentation yourself by calling "make doc". Note that you need Doxygen and GraphViz available at configure time to be able to build the documentation. If you need help, please ask on the [PDELab mailinglist][5] for now. Bugs can be submitted to the [bugtracker][6] instead. See the file [CHANGELOG.md][8] for recent changes to the library. Dependencies ------------ TypeTree depends on the following software packages: * The dune-common library from DUNE, version 2.4-dev. The dependency is actually very weak, and you can easily use the library standalone by replacing the few convenience components reused from dune-common (and by replacing the build system, of course). * TypeTree uses lots and lots of templates, so you need a decent C++ compiler. This release requires a compiler that is at least compatible with GCC 4.7 in C++11 mode, so it whould work with all recent versions of GCC since version 4.7, modern versions of the clang compiler (3.2+) and very recent versions of ICC (icpc 15.0.0+). License ------- The TypeTree library, headers and test programs are free open-source software, dual-licensed under version 3 or later of the GNU Lesser General Public License and version 2 of the GNU General Public License with a special run-time exception. See the file [LICENSE.md][7] for full copying permissions. Installation ------------ For installation instructions please see the [DUNE website][2]. Links ----- [0]: http://www.dune-project.org/pdelab/ [1]: http://www.dune-project.org [2]: http://www.dune-project.org/doc/installation-notes.html [4]: http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.license [5]: http://lists.dune-project.org/mailman/listinfo/dune-pdelab [6]: http://gitlab.dune-project.org/pdelab/dune-typetree/issues [7]: LICENSE.md [8]: CHANGELOG.md dune-typetree-2.5.0/cmake/000077500000000000000000000000001302546717000153755ustar00rootroot00000000000000dune-typetree-2.5.0/cmake/modules/000077500000000000000000000000001302546717000170455ustar00rootroot00000000000000dune-typetree-2.5.0/cmake/modules/CMakeLists.txt000066400000000000000000000002671302546717000216120ustar00rootroot00000000000000set(modules DuneTypetreeMacros.cmake FindCXXDecltype.cmake FindCXXTemplateAliases.cmake FindGCCTypeof.cmake ) install(FILES ${modules} DESTINATION ${DUNE_INSTALL_MODULEDIR}) dune-typetree-2.5.0/cmake/modules/DuneTypetreeMacros.cmake000066400000000000000000000001231302546717000236250ustar00rootroot00000000000000find_package(CXXTemplateAliases) find_package(CXXDecltype) find_package(GCCTypeof) dune-typetree-2.5.0/cmake/modules/FindCXXDecltype.cmake000066400000000000000000000012301302546717000230000ustar00rootroot00000000000000# Module that checks whether the compiler supports # the C++11 keyword decltype. # # Sets the following variable: # HAVE_STD_DECLTYPE # # perform tests include(CheckCXXSourceCompiles) check_cxx_source_compiles(" template struct check_equal; template struct check_equal { static const int result = 0; }; struct A; const A& foo(); int main(void){ return check_equal::result; }" HAVE_STD_DECLTYPE) # Report success correctly in summary include(FindPackageHandleStandardArgs) find_package_handle_standard_args( "CXXDecltype" DEFAULT_MSG HAVE_STD_DECLTYPE ) dune-typetree-2.5.0/cmake/modules/FindCXXTemplateAliases.cmake000066400000000000000000000014321302546717000243100ustar00rootroot00000000000000# Module that checks whether the compiler supports # C++11 template aliases. # # Sets the following variable: # HAVE_TEMPLATE_ALIASES # # perform tests include(CheckCXXSourceCompiles) check_cxx_source_compiles(" template struct A {}; template using A1 = A; template using A2 = A; template struct assert_equal; template struct assert_equal {}; int main() { assert_equal,A2 >(); assert_equal,A1 >(); return 0; }" HAVE_TEMPLATE_ALIASES) # Report success correctly in summary include(FindPackageHandleStandardArgs) find_package_handle_standard_args( "CXXTemplateAliases" DEFAULT_MSG HAVE_TEMPLATE_ALIASES ) dune-typetree-2.5.0/cmake/modules/FindGCCTypeof.cmake000066400000000000000000000013411302546717000224320ustar00rootroot00000000000000# Module that checks whether the compiler supports # the GCC extension __typeof__, which can serve as # a limited fallback for decltype on some older compilers. # # Sets the following variable: # HAVE_GCC___TYPEOF__ # # perform tests include(CheckCXXSourceCompiles) check_cxx_source_compiles(" template struct check_equal; template struct check_equal { static const int result = 0; }; struct A {}; A foo(); int main(void){ return check_equal<__typeof__(foo()),A>::result; }" HAVE_GCC___TYPEOF__) # Report success correctly in summary include(FindPackageHandleStandardArgs) find_package_handle_standard_args( "GCCTypeof" DEFAULT_MSG HAVE_STD_DECLTYPE ) dune-typetree-2.5.0/config.h.cmake000066400000000000000000000032331302546717000170130ustar00rootroot00000000000000/* begin dune-typetree put the definitions for config.h specific to your project here. Everything above will be overwritten */ /* begin private */ /* Name of package */ #define PACKAGE "@DUNE_MOD_NAME@" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "@DUNE_MAINTAINER@" /* Define to the full name of this package. */ #define PACKAGE_NAME "@DUNE_MOD_NAME@" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "@DUNE_MOD_NAME@ @DUNE_MOD_VERSION@" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "@DUNE_MOD_NAME@" /* Define to the home page for this package. */ #define PACKAGE_URL "@DUNE_MOD_URL@" /* Define to the version of this package. */ #define PACKAGE_VERSION "@DUNE_MOD_VERSION@" /* end private */ /* Define to the version of dune-typetree */ #define DUNE_TYPETREE_VERSION "${DUNE_TYPETREE_VERSION}" /* Define to the major version of dune-typetree */ #define DUNE_TYPETREE_VERSION_MAJOR ${DUNE_TYPETREE_VERSION_MAJOR} /* Define to the minor version of dune-typetree */ #define DUNE_TYPETREE_VERSION_MINOR ${DUNE_TYPETREE_VERSION_MINOR} /* Define to the revision of dune-typetree */ #define DUNE_TYPETREE_VERSION_REVISION ${DUNE_TYPETREE_VERSION_REVISION} /* Define to 1 if std::initializer_list is supported. */ #cmakedefine HAVE_INITIALIZER_LIST 1 /* Define to 1 if template aliases are supported. */ #cmakedefine HAVE_TEMPLATE_ALIASES 1 /* Define to 1 if decltype if supported. */ #cmakedefine HAVE_STD_DECLTYPE 1 /* Define to 1 if GCC's __typeof__ extension is supported. */ #cmakedefine HAVE_GCC___TYPEOF__ 1 /* end dune-typetree */ dune-typetree-2.5.0/doc/000077500000000000000000000000001302546717000150625ustar00rootroot00000000000000dune-typetree-2.5.0/doc/CMakeLists.txt000066400000000000000000000000321302546717000176150ustar00rootroot00000000000000add_subdirectory(doxygen) dune-typetree-2.5.0/doc/doxygen/000077500000000000000000000000001302546717000165375ustar00rootroot00000000000000dune-typetree-2.5.0/doc/doxygen/.gitignore000066400000000000000000000001041302546717000205220ustar00rootroot00000000000000doxyerr.log Doxyfile Doxyfile.in doxygen-tag doxygen.log html/ pdf/ dune-typetree-2.5.0/doc/doxygen/CMakeLists.txt000066400000000000000000000001001302546717000212660ustar00rootroot00000000000000# Create and install doxygen documentation add_doxygen_target() dune-typetree-2.5.0/doc/doxygen/Doxylocal000066400000000000000000000002301302546717000204130ustar00rootroot00000000000000INPUT += @srcdir@/mainpage.txt \ @srcdir@/modules.txt \ @top_srcdir@/dune EXCLUDE += @top_srcdir@/test EXTRA_PACKAGES = amsmath dune-typetree-2.5.0/doc/doxygen/mainpage.txt000066400000000000000000000006431302546717000210640ustar00rootroot00000000000000/** \mainpage dune-typetree Automatic Documentation \section intro Introduction Welcome to the TypeTree documentation pages. This documentation has been generated using Doxygen, a free source code documentation system for documenting C/C++ code. \section mods Modules The best way to start is from the page \subpage modules which gives you access to the documentation by category. */ /** \page modules Modules */ dune-typetree-2.5.0/doc/doxygen/modules.txt000066400000000000000000000000521302546717000207450ustar00rootroot00000000000000/** @defgroup TypeTree dune-typetree */ dune-typetree-2.5.0/dune-typetree.pc.in000066400000000000000000000004351302546717000200420ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ CXX=@CXX@ CC=@CC@ DEPENDENCIES=@REQUIRES@ Name: @PACKAGE_NAME@ Version: @VERSION@ Description: dune-typetree module URL: http://dune-project.org/ Requires: ${DEPENDENCIES} Libs: Cflags: -I${includedir} dune-typetree-2.5.0/dune.module000066400000000000000000000002151302546717000164550ustar00rootroot00000000000000Module: dune-typetree Version: 2.5.0 Maintainer: steffen.muething@iwr.uni-heidelberg.de Depends: dune-common (>= 2.5.0) Whitespace-Hook: Yes dune-typetree-2.5.0/dune/000077500000000000000000000000001302546717000152505ustar00rootroot00000000000000dune-typetree-2.5.0/dune/CMakeLists.txt000066400000000000000000000000331302546717000200040ustar00rootroot00000000000000add_subdirectory(typetree) dune-typetree-2.5.0/dune/typetree/000077500000000000000000000000001302546717000171115ustar00rootroot00000000000000dune-typetree-2.5.0/dune/typetree/CMakeLists.txt000066400000000000000000000012121302546717000216450ustar00rootroot00000000000000install(FILES accumulate_static.hh applytochildrensingletree.hh applytochildrentreepair.hh childextraction.hh compositenode.hh exceptions.hh filteredcompositenode.hh filters.hh fixedcapacitystack.hh generictransformationdescriptors.hh leafnode.hh nodeinterface.hh nodetags.hh pairtraversal.hh powercompositenodetransformationtemplates.hh powernode.hh proxynode.hh simpletransformationdescriptors.hh transformation.hh transformationutilities.hh traversal.hh traversalutilities.hh treepath.hh typetraits.hh typetree.hh utility.hh visitor.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/typetree) dune-typetree-2.5.0/dune/typetree/accumulate_static.hh000066400000000000000000000456011302546717000231320ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_ACCUMULATE_STATIC_HH #define DUNE_TYPETREE_ACCUMULATE_STATIC_HH #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Tree Traversal * \ingroup TypeTree * \{ */ //! Statically combine two values of type result_type using ||. template struct or_ { template struct reduce { static const result_type result = r1 || r2; }; }; //! Statically combine two values of type result_type using &&. template struct and_ { template struct reduce { static const result_type result = r1 && r2; }; }; //! Statically combine two values of type result_type using +. template struct plus { template struct reduce { static const result_type result = r1 + r2; }; }; //! Statically combine two values of type result_type using -. template struct minus { template struct reduce { static const result_type result = r1 - r2; }; }; //! Statically combine two values of type result_type using *. template struct multiply { template struct reduce { static const result_type result = r1 * r2; }; }; //! Statically combine two values of type result_type by returning their minimum. template struct min { template struct reduce { static const result_type result = r1 < r2 ? r1 : r2; }; }; //! Statically combine two values of type result_type by returning their maximum. template struct max { template struct reduce { static const result_type result = r1 > r2 ? r1 : r2; }; }; namespace { // implementation of the traversal algorithm //! helper struct to decide whether or not to perform the per-node calculation on the current node. Default case: ignore the node. template struct accumulate_node_helper { typedef typename Functor::result_type result_type; static const result_type result = current_value; }; //! helper struct to decide whether or not to perform the per-node calculation on the current node. Specialization: Perform the calculation. template struct accumulate_node_helper { typedef typename Functor::result_type result_type; static const result_type result = Reduction::template reduce::result>::result; }; //! Per node type algorithm struct. Prototype. template struct accumulate_value; //! Leaf node specialization. template struct accumulate_value { typedef typename Functor::result_type result_type; static const result_type result = accumulate_node_helper::value>::result; }; //! Iteration over children of a composite node. template struct accumulate_over_children { typedef typename Functor::result_type result_type; typedef typename TreePathPushBack::type child_tree_path; typedef typename Node::template Child::Type child; static const result_type child_result = accumulate_value>::result; static const result_type result = accumulate_over_children::result; }; //! end of iteration. template struct accumulate_over_children { typedef typename Functor::result_type result_type; static const result_type result = current_value; }; //! Generic composite node specialization. We are doing the calculation at compile time and thus have to use static iteration for //! the PowerNode as well. template struct accumulate_value_generic_composite_node { typedef typename Functor::result_type result_type; static const result_type child_result = accumulate_over_children::value>::result; static const result_type result = accumulate_node_helper::value>::result; }; //! PowerNode specialization. template struct accumulate_value : public accumulate_value_generic_composite_node {}; //! CompositeNode specialization. template struct accumulate_value : public accumulate_value_generic_composite_node {}; } // anonymous namespace //! Statically accumulate a value over the nodes of a TypeTree. /** * This struct implements an algorithm for iterating over a tree and * calculating an accumulated value at compile time. * * \tparam Tree The tree to iterate over. * \tparam Functor The compile-time functor used for visiting each node. * * This functor must implement the following interface: * * \code * struct AccumulationFunctor * { * * // The result type of the overall computation. * typedef ... result_type; * * // Decide whether to include the given node in the calculation * // or to skip it. * template * struct doVisit * { * static const bool value = true; * }; * * // Calculate the per-node result. * template * struct visit * { * static const result_type result = ...; * }; * * }; * \endcode * * \tparam Reduction The reduction operator used to accumulate the per-node * results. * * The reduction operator must implement the following interface: * * \code * template * struct ReductionOperator * { * * // combine two per-node results * template * struct reduce * { * static const result_type result = ...; * }; * * }; * \endcode * * \tparam startValue The starting value fed into the initial accumulation step. */ template struct AccumulateValue { //! The result type of the computation. typedef typename Functor::result_type result_type; //! The accumulated result of the computation. static const result_type result = accumulate_value,NodeTag>::result; }; //! Tag selecting a type reduction algorithm that visits the tree in //! postorder and performs a flat reduction over the resulting type list. struct flattened_reduction; //! Tag selecting a type reduction algorithm that visits the tree in //! postorder and performs a bottom-up reduction over the resulting type list. struct bottom_up_reduction; namespace { // implementation of the traversal algorithm //! helper struct to decide whether or not to perform the per-node calculation on the current node. Default case: ignore the node. //! The helper cannot use the Policy parameter, as we want to invoke it with different reductions. template struct accumulate_type_node_helper { typedef current_type type; }; //! helper struct to decide whether or not to perform the per-node calculation on the current node. Specialization: Perform the calculation. template struct accumulate_type_node_helper { typedef typename Reduction::template reduce< current_type, typename Functor::template visit< Node, TreePath >::type >::type type; }; //! Per node type algorithm struct. Prototype. template struct accumulate_type; //! Leaf node specialization. template struct accumulate_type { typedef typename accumulate_type_node_helper< LeafNode, typename Policy::functor, typename Policy::sibling_reduction, current_type, TreePath, Policy::functor::template doVisit< LeafNode, TreePath>::value >::type type; }; //! Switch for propagation of current type down the tree based on the algorithm //! specified in the policy. template struct propagate_type_down_tree; //! Always continue reduction with the current result type template struct propagate_type_down_tree< current_type, tree_path, start_type, bottom_up_reduction > { typedef current_type type; }; //! When descending to a new node, do not propagate current result type template struct propagate_type_down_tree< current_type, tree_path, start_type, flattened_reduction > { typedef typename std::conditional< TreePathBack::value == 0, start_type, current_type >::type type; }; //! Iteration over children of a composite node. template struct accumulate_type_over_children { typedef typename TreePathPushBack::type child_tree_path; typedef typename Node::template Child::Type child; typedef typename accumulate_type< child, Policy, // apply reduction choice (flat / hierarchic) typename propagate_type_down_tree< current_type, child_tree_path, typename Policy::start_type, typename Policy::reduction_strategy >::type, child_tree_path, NodeTag >::type child_result_type; typedef typename accumulate_type_over_children< Node, Policy, child_result_type, TreePath, i+1, n >::type type; }; //! end of iteration. template struct accumulate_type_over_children { typedef current_type type; }; //! Generic composite node specialization. We are doing the calculation at compile time and thus have to use static iteration for //! the PowerNode as well. template struct accumulate_type_generic_composite_node { typedef typename accumulate_type_over_children< Node, Policy, current_type, TreePath, 0, StaticDegree::value >::type children_result_type; typedef typename accumulate_type_node_helper< Node, typename Policy::functor, typename Policy::parent_child_reduction, children_result_type, TreePath, Policy::functor::template doVisit< Node, TreePath >::value >::type type; }; //! PowerNode specialization. template struct accumulate_type : public accumulate_type_generic_composite_node {}; //! CompositeNode specialization. template struct accumulate_type : public accumulate_type_generic_composite_node {}; } // anonymous namespace /** * Policy for controlling the static type accumulation algorithm AccumulateType. * See the documentation of nested types for further information. * * * \tparam startType The start type fed into the initial accumulation step. */ template< typename Functor, typename Reduction, typename StartType, typename ParentChildReduction = Reduction, typename ReductionAlgorithm = flattened_reduction > struct TypeAccumulationPolicy { /** * The compile-time functor used for visiting each node. * * This functor must implement the following interface: * * \code * struct AccumulationFunctor * { * * // Decide whether to include the given node in the calculation * // or to skip it. * template * struct doVisit * { * static const bool value = true; * }; * * // Calculate the per-node result. * template * struct visit * { * typedef ... type; * }; * * }; * \endcode */ typedef Functor functor; /** * The reduction operator used to accumulate the per-node results of sibling nodes. * * The reduction operator must implement the following interface: * * \code * struct ReductionOperator * { * * // combine two per-node results * template * struct reduce * { * typedef ... type; * }; * * }; * \endcode */ typedef Reduction sibling_reduction; /** * The reduction operator used to combine the accumulated result of all * children of a node with the result of the parent node. * * This operator has the same interface as sibling_reduction. */ typedef ParentChildReduction parent_child_reduction; /** * The initial result type. * This type will be feed as first operand to the reduction operators * when doing the first accumulation (and there is no calculated result * to accumulate with yet). */ typedef StartType start_type; /** * The strategy for performing the type reduction with regard to the tree structure. * Valid values are flattened_reduction and bottom_up_reduction. */ typedef ReductionAlgorithm reduction_strategy; }; //! Statically accumulate a type over the nodes of a TypeTree. /** * This struct implements an algorithm for iterating over a tree and * calculating an accumulated type at compile time. * * \tparam Tree The tree to iterate over. * \tparam Policy Model of TypeAccumulationPolicy controlling the behavior * of the algorithm. */ template struct AccumulateType { //! The accumulated result of the computation. typedef typename accumulate_type< Tree, Policy, typename Policy::start_type, TreePath<>, NodeTag >::type type; }; //! \} group Tree Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_ACCUMULATE_STATIC_HH dune-typetree-2.5.0/dune/typetree/applytochildrensingletree.hh000066400000000000000000000226171302546717000247250ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH #define DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Tree Traversal * \ingroup TypeTree * \{ */ #ifndef DOXYGEN // these are all internals and not public API. // forward declaration of main engine struct template struct ApplyToTree; namespace { // For the CompositeNode, we do need a TMP for iterating over the // children. Note that we use an index that counts down instead of up. // This allows us to specialize the TMP for the last child, where we // do not want to invoke the infix visitor on the CompositeNode. // There are two versions of this TMP, one for iteration with a static TreePath, and one // for iteration with a dynamic TreePath. // ******************************************************************************** // Static Version // ******************************************************************************** template struct apply_to_children_fully_static { template static void apply(N&& n, V&& v, TreePath tp) { // make sure we do not try to work with references to the actual types typedef typename std::remove_reference::type Node; typedef typename std::remove_reference::type Visitor; // get child type typedef typename Node::template Child::Type C; // extend TreePath by child index typedef typename TreePathPushBack::type ChildTreePath; // is the visitor interested in this child? const bool visit = Visitor::template VisitChild::value; // beforeChild() gets called regardless of the value of visit v.beforeChild(std::forward(n),n.template child(),tp,std::integral_constant()); // traverse to child ApplyToTree,visit>::apply(n.template child(), std::forward(v), ChildTreePath()); // afterChild() gets called regardless of the value of visit v.afterChild(std::forward(n),n.template child(),tp,std::integral_constant()); // we are not at the last child (that is specialized), so call infix visitor callback v.in(std::forward(n),tp); // continue with next child apply_to_children_fully_static::apply(std::forward(n), std::forward(v), tp); } }; // Specialization for last child. This specialization stops the recursion and // does not call the infix visitor on the CompositeNode. template struct apply_to_children_fully_static<1,count> { template static void apply(N&& n, V&& v, TreePath tp) { typedef typename std::remove_reference::type Node; typedef typename std::remove_reference::type Visitor; typedef typename Node::template Child::Type C; typedef typename TreePathPushBack::type ChildTreePath; const bool visit = Visitor::template VisitChild::value; v.beforeChild(std::forward(n),n.template child(),tp,std::integral_constant()); ApplyToTree,visit>::apply(n.template child(), std::forward(v), ChildTreePath()); v.afterChild(std::forward(n),n.template child(),tp,std::integral_constant()); } }; // Specialization for CompositeNode without any children. template<> struct apply_to_children_fully_static<0,0> { template static void apply(N&& n, V&& v, TreePath tp) {} }; // ******************************************************************************** // Dynamic Version // ******************************************************************************** template struct apply_to_children_dynamic { template static void apply(N&& n, V&& v, TreePath tp) { typedef typename std::remove_reference::type Node; typedef typename std::remove_reference::type Visitor; typedef typename Node::template Child::Type C; const bool visit = Visitor::template VisitChild::value; v.beforeChild(std::forward(n),n.template child(),tp.view(),count-inverse_k); tp.push_back(count-inverse_k); ApplyToTree,visit>::apply(n.template child(), std::forward(v), tp); tp.pop_back(); v.afterChild(std::forward(n),n.template child(),tp.view(),count-inverse_k); v.in(std::forward(n),tp.view()); apply_to_children_dynamic::apply(std::forward(n), std::forward(v), tp); } }; // Specialization for last child. This specialization stops the recursion and // does not call the infix visitor on the CompositeNode. template struct apply_to_children_dynamic<1,count> { template static void apply(N&& n, V&& v, TreePath tp) { typedef typename std::remove_reference::type Node; typedef typename std::remove_reference::type Visitor; typedef typename Node::template Child::Type C; const bool visit = Visitor::template VisitChild::value; v.beforeChild(std::forward(n),n.template child(),tp.view(),count-1); tp.push_back(count-1); ApplyToTree,visit>::apply(n.template child(), std::forward(v), tp); tp.pop_back(); v.afterChild(std::forward(n),n.template child(),tp.view(),count-1); } }; // Specialization for CompositeNode without any children. template<> struct apply_to_children_dynamic<0,0> { template static void apply(N&& n, V&& v, TreePath tp) {} }; // helper struct for automatically picking the right traversal // algorithm variant template struct apply_to_children; template struct apply_to_children : public apply_to_children_fully_static {}; template struct apply_to_children : public apply_to_children_dynamic {}; } // anonymous namespace // Base class for composite node traversal // The traversal algorithm is identical for CompositeNode // and PowerNode in the case of static traversal, // so the implementation can be bundled // in a single base class. struct ApplyToGenericCompositeNode { template static void apply(N&& n, V&& v, TreePath tp) { v.pre(std::forward(n),tp); typedef typename std::remove_reference::type Node; typedef typename std::remove_reference::type Visitor; apply_to_children::value>::apply(std::forward(n), std::forward(v), tp); v.post(std::forward(n),tp); } }; #endif // DOXYGEN //! \} group Tree Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_APPLYTOCHILDRENSINGLETREE_HH dune-typetree-2.5.0/dune/typetree/applytochildrentreepair.hh000066400000000000000000000303311302546717000243670ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_APPLYTOCHILDRENTREEPAIR_HH #define DUNE_TYPETREE_APPLYTOCHILDRENTREEPAIR_HH #include #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Tree Traversal * \ingroup TypeTree * \{ */ #ifndef DOXYGEN // these are all internals and not public API. Only access is using applyToTree(). // forward declaration of main engine struct template struct ApplyToTreePair; namespace { // TMP for traversing the children of non-leaf nodes with a static TreePath. // Due to the static TreePath, we have to use this TMP for both CompositeNode // and PowerNode. template struct apply_to_children_pair_fully_static { template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { typedef typename std::remove_reference::type::template Child::Type C1; typedef typename std::remove_reference::type::template Child::Type C2; typedef typename TreePathPushBack::type ChildTreePath; const bool visit = std::remove_reference::type ::template VisitChild::type, C1, typename std::remove_reference::type, C2, ChildTreePath>::value; v.beforeChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp,std::integral_constant()); ApplyToTreePair::type::treePathType, NodeTag, NodeTag, visit>::apply(n1.template child(), n2.template child(), std::forward(v), ChildTreePath()); v.afterChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp,std::integral_constant()); v.in(std::forward(n1),std::forward(n2),tp); apply_to_children_pair_fully_static::apply(std::forward(n1), std::forward(n2), std::forward(v), tp); } }; // Specialization for last child. This specialization stops the recursion and // does not call the infix visitor. template struct apply_to_children_pair_fully_static<1,count> { template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { typedef typename std::remove_reference::type::template Child::Type C1; typedef typename std::remove_reference::type::template Child::Type C2; typedef typename TreePathPushBack::type ChildTreePath; const bool visit = std::remove_reference::type ::template VisitChild::type, C1, typename std::remove_reference::type, C2, ChildTreePath>::value; v.beforeChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp,std::integral_constant()); ApplyToTreePair::type::treePathType, NodeTag, NodeTag, visit>::apply(n1.template child(), n2.template child(), std::forward(v), ChildTreePath()); v.afterChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp,std::integral_constant()); } }; // Specialization for CompositeNode without any children. template<> struct apply_to_children_pair_fully_static<0,0> { template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) {} }; // TMP for traversing the children of non-leaf nodes with a dynamic TreePath. // This is used if at least one of the nodes is a CompositeNode. // If both nodes are PowerNodes, this will not be instantiated and we simply // use a runtime loop to iterate over the children. template struct apply_to_children_pair_dynamic { template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { typedef typename std::remove_reference::type::template Child::Type C1; typedef typename std::remove_reference::type::template Child::Type C2; const bool visit = std::remove_reference::type ::template VisitChild::type, C1, typename std::remove_reference::type, C2, typename TreePath::ViewType>::value; v.beforeChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp.view(),count-inverse_k); tp.push_back(count-inverse_k); ApplyToTreePair::type::treePathType, NodeTag, NodeTag, visit>::apply(n1.template child(), n2.template child(), std::forward(v), tp); tp.pop_back(); v.afterChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp.view(),count-inverse_k); v.in(std::forward(n1),std::forward(n2),tp.view()); apply_to_children_pair_dynamic::apply(std::forward(n1), std::forward(n2), std::forward(v), tp); } }; // Specialization for last child. This specialization stops the recursion and // does not call the infix visitor on the CompositeNode. template struct apply_to_children_pair_dynamic<1,count> { template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { typedef typename std::remove_reference::type::template Child::Type C1; typedef typename std::remove_reference::type::template Child::Type C2; const bool visit = std::remove_reference::type ::template VisitChild::type, C1, typename std::remove_reference::type, C2, typename TreePath::ViewType>::value; v.beforeChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp.view(),count-1); tp.push_back(count-1); ApplyToTreePair::type::treePathType, NodeTag, NodeTag, visit>::apply(n1.template child(), n2.template child(), std::forward(v), tp); tp.pop_back(); v.afterChild(std::forward(n1),n1.template child(), std::forward(n2),n2.template child(), tp.view(),count-1); } }; // Specialization for CompositeNode without any children. template<> struct apply_to_children_pair_dynamic<0,0> { template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) {} }; // helper struct for automatically picking the correct child // traversal algorithm variant template struct apply_to_children_pair; template struct apply_to_children_pair : public apply_to_children_pair_fully_static {}; template struct apply_to_children_pair : public apply_to_children_pair_dynamic {}; } // anonymous namespace // Base class for composite node traversal template struct ApplyToGenericCompositeNodePair { // one node is a leaf -> treat node pair as a leaf template static typename std::enable_if<(std::remove_reference::type::isLeaf || std::remove_reference::type::isLeaf)>::type apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { v.leaf(std::forward(n1),std::forward(n2),tp.view()); } // both nodes contain children -> iterate over them template static typename std::enable_if::type::isLeaf || std::remove_reference::type::isLeaf)>::type apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { v.pre(std::forward(n1),std::forward(n2),tp.view()); // make sure both nodes have the same number of children - otherwise, it // would be difficult to match the children to each other. static_assert(StaticDegree::value == StaticDegree::value, "non-leaf nodes with different numbers of children " \ "are not allowed during simultaneous grid traversal"); apply_to_children_pair::value>::apply(std::forward(n1), std::forward(n2), std::forward(v), tp); v.post(std::forward(n1),std::forward(n2),tp.view()); } }; #endif // DOXYGEN //! \} group Tree Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_APPLYTOCHILDRENTREEPAIR_HH dune-typetree-2.5.0/dune/typetree/childextraction.hh000066400000000000000000000345631302546717000226310ustar00rootroot00000000000000// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=8 sw=2 sts=2: #ifndef DUNE_TYPETREE_CHILDEXTRACTION_HH #define DUNE_TYPETREE_CHILDEXTRACTION_HH #include #include #include #include #include #include #include namespace Dune { namespace TypeTree { //! \addtogroup TypeTreeChildExtraction Child Extraction //! Utility functions and metafunctions for extracting children from a TypeTree. //! \ingroup TypeTree //! \{ #ifndef DOXYGEN namespace impl { // ******************************************************************************** // end of the recursion, there are no child indices, so just return the node itself // ******************************************************************************** struct IsPointerLike { template auto require(const Node& node) -> decltype(*node); }; template auto child(Node&& node) -> decltype(std::forward(node)) { return std::forward(node); } // for now, this wants the passed-in object to be pointer-like. I don't know how clever // that is in the long run, though. template(),int> = 0> auto childStorage(Node&& node) { return std::forward(node); } // ******************************************************************************** // next index is a compile-time constant // ******************************************************************************** // we need a concept to make sure that the node has a templated child() // method struct HasTemplateChildMethod { template auto require(const Node& node) -> decltype(node.template child<0>()); }; // The actual implementation is rather simple, we just use an overload that requires the first index // to be an index_constant, get the child and then recurse. // It only gets ugly due to the enable_if, but without that trick, the error messages for the user // can get *very* obscure (they are bad enough as it is). template() && (i < StaticDegree::value), int>::type = 0> decltype(auto) child(Node&& node, index_constant, J... j) { return child(std::forward(node).template child(),j...); } template>())>() && (i < StaticDegree())>::value), int>::type = 0> decltype(auto) childStorage(Node&& node, index_constant, J... j) { return childStorage(std::forward(node)->template childStorage(),j...); } // This overload is only present to give useful compiler // error messages via static_assert in case the other overloads // fail. template()) || (i >= StaticDegree::value), int>::type = 0> void child(Node&& node, index_constant, J... j) { static_assert(Dune::models(), "Node does not have a template method child()"); static_assert(i < StaticDegree::value, "Child index out of range"); } // ******************************************************************************** // next index is a run-time value // ******************************************************************************** // The actual implemention here overloads on std::size_t. It is a little less ugly because it currently // has a hard requirement on the PowerNode Tag (although only using is_convertible, as tags can be // inherited (important!). template decltype(auto) child( Node&& node, std::enable_if_t< std::is_convertible< NodeTag, PowerNodeTag >{}, std::size_t> i, J... j ) { return child(std::forward(node).child(i),j...); } template decltype(auto) childStorage( Node&& node, std::enable_if_t< std::is_convertible< NodeTag())>, PowerNodeTag >{}, std::size_t> i, J... j ) { return childStorage(std::forward(node)->childStorage(i),j...); } template decltype(auto) child(Node&& node, HybridTreePath tp, std::index_sequence) { return child(std::forward(node),treePathEntry(tp)...); } template decltype(auto) childStorage(Node&& node, HybridTreePath tp, std::index_sequence) { return childStorage(std::forward(node),treePathEntry(tp)...); } } // namespace imp #endif // DOXYGEN //! Extracts the child of a node given by a sequence of compile-time and run-time indices. /** * Use this function to extract a (possibly indirect) child of a TypeTree node. * * Example: * * \code{.cc} * using namespace Dune::TypeTree::Indices; // for compile-time indices * auto&& c = child(node,_4,2,_0,1); * \endcode * * returns the second child of the first child of the third child * of the fifth child of node, where some child lookups were done using * a compile-time index and some using a run-time index. * * \param node The node from which to extract the child. * \param indices... A list of indices that describes the path into the tree to the * wanted child. These parameters can be a combination of run time indices * (for tree nodes that allow accessing their children using run time information, * like PowerNode) and instances of index_constant, which work for all types of inner * nodes. * \return A reference to the child, its cv-qualification depends on the passed-in node. */ template #ifdef DOXYGEN ImplementationDefined child(Node&& node, Indices... indices) #else decltype(auto) child(Node&& node, Indices... indices) #endif { return impl::child(std::forward(node),indices...); } template #ifdef DOXYGEN ImplementationDefined child(Node&& node, Indices... indices) #else auto childStorage(Node&& node, Indices... indices) #endif { //static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty list of child indices"); return impl::childStorage(&node,indices...); } //! Extracts the child of a node given by a static TreePath object. /** * Use this function to extract a (possibly indirect) child of a TypeTree node. * * Example: * * \code{.cc} * Dune::TypeTree::TreePath<4,2,0,1> tp; * auto&& c = child(node,tp); * \endcode * * returns the second child of the first child of the third child * of the fifth child of node. * * \param node The node from which to extract the child. * \param treePath A TreePath object that describes the path into the tree to the * wanted child. * \return A reference to the child, its cv-qualification depends on the passed-in node. */ template #ifdef DOXYGEN ImplementationDefined child(Node&& node, TreePath treePath) #else decltype(auto) child(Node&& node, TreePath) #endif { return child(std::forward(node),index_constant{}...); } template #ifdef DOXYGEN ImplementationDefined childStorage(Node&& node, TreePath treePath) #else auto childStorage(Node&& node, TreePath) #endif { static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath"); return impl::childStorage(&node,index_constant{}...); } //! Extracts the child of a node given by a HybridTreePath object. /** * Use this function to extract a (possibly indirect) child of a TypeTree node. * * Example: * * \code{.cc} * using namespace Dune::TypeTree::Indices; // for compile-time indices * auto tp = Dune::TypeTree::hybridTreePath(_4,2,_0,1); * auto&& c = child(node,tp); * \endcode * * returns the second child of the first child of the third child * of the fifth child of node, where some child lookups were done using * a compile-time index and some using a run-time index. * * \param node The node from which to extract the child. * \param tree{ath A HybridTreePath that describes the path into the tree to the * wanted child. This tree path object can be a combination of run time indices * (for tree nodes that allow accessing their children using run time information, * like PowerNode) and instances of index_constant, which work for all types of inner * nodes. * \return A reference to the child, its cv-qualification depends on the passed-in node. */ template #ifdef DOXYGEN ImplementationDefined child(Node&& node, HybridTreePath treePath) #else decltype(auto) child(Node&& node, HybridTreePath tp) #endif { return impl::child(std::forward(node),tp,std::index_sequence_for{}); } template #ifdef DOXYGEN ImplementationDefined child(Node&& node, HybridTreePath treePath) #else auto childStorage(Node&& node, HybridTreePath tp) #endif { static_assert(sizeof...(Indices) > 0, "childStorage() cannot be called with an empty TreePath"); return impl::childStorage(&node,tp,std::index_sequence_for{}); } #ifndef DOXYGEN namespace impl { template struct _Child { using type = std::decay_t(),index_constant{}...))>; }; } #endif // DOXYGEN //! Template alias for the type of a child node given by a list of child indices. /** * This template alias is implemented in terms of the free-standing child() functions and uses those * in combination with decltype() to extract the child type. * \tparam Node The type of the parent node. * \tparam indices A list of index values the describes the path to the wanted child. */ template using Child = typename impl::_Child::type; #ifndef DOXYGEN namespace impl { template struct _ChildForTreePath { using type = typename std::decay(),std::declval()))>::type; }; } #endif // DOXYGEN //! Template alias for the type of a child node given by a TreePath or a HybridTreePath type. /** * This template alias is implemented in terms of the free-standing child() functions and uses those * in combination with decltype() to extract the child type. It supports both TreePath and * HybridTreePath. * * \tparam Node The type of the parent node. * \tparam TreePath The type of a TreePath or a HybridTreePath that describes the path to the wanted child. */ template using ChildForTreePath = typename impl::_ChildForTreePath::type; #ifndef DOXYGEN namespace impl { // By default, types are flat indices if they are integral template struct _is_flat_index { using type = std::is_integral; }; // And so is any index_constant template struct _is_flat_index> { using type = std::true_type; }; } #endif // DOXYGEN //! Type trait that determines whether T is a flat index in the context of child extraction. /* * This type trait can be used to check whether T is a flat index (i.e. either `std::size_t` * or `index_constant`). The type trait normalizes T before doing the check, so it will also * work correctly for references and cv-qualified types. */ template using is_flat_index = typename impl::_is_flat_index>::type; #ifndef DOXYGEN namespace impl { // helper struct to perform lazy return type evaluation in the forwarding member child() methods // of nodes template struct _lazy_member_child_decltype { template struct evaluate { using type = decltype(Dune::TypeTree::child(std::declval(),std::declval()...)); }; }; // helper function for check in member child() functions that tolerates being passed something that // isn't a TreePath. It will just return 0 in that case template constexpr typename std::enable_if< is_flat_index{}, bool >::type _non_empty_tree_path(T) { return false; } template constexpr typename std::enable_if< !is_flat_index{}, bool >::type _non_empty_tree_path(T t) { return treePathSize(t) > 0; } } #endif // DOXYGEN //! \} group TypeTree } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_CHILDEXTRACTION_HH dune-typetree-2.5.0/dune/typetree/compositenode.hh000066400000000000000000000202551302546717000223060ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_COMPOSITENODE_HH #define DUNE_TYPETREE_COMPOSITENODE_HH #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ //! Base class for composite nodes based on variadic templates. template class CompositeNode { public: //! The type tag that describes a CompositeNode. typedef CompositeNodeTag NodeTag; //! The type used for storing the children. typedef std::tuple... > NodeStorage; //! A tuple storing the types of all children. typedef std::tuple ChildTypes; //! Mark this class as non leaf in the \ref TypeTree. static const bool isLeaf = false; //! Mark this class as a non power in the \ref TypeTree. static const bool isPower = false; //! Mark this class as a composite in the \ref TypeTree. static const bool isComposite = true; //! The number of children. static const std::size_t CHILDREN = sizeof...(Children); static constexpr std::size_t degree() { return sizeof...(Children); } //! Access to the type and storage type of the i-th child. template struct Child { static_assert((k < CHILDREN), "child index out of range"); //! The type of the child. typedef typename std::tuple_element::type Type; //! The type of the child. typedef typename std::tuple_element::type type; //! The storage type of the child. typedef typename std::tuple_element::type Storage; //! The const storage type of the child. typedef std::shared_ptr::type> ConstStorage; }; //! @name Child Access //! @{ //! Returns the i-th child. /** * \returns a reference to the i-th child. */ template typename Child::Type& child(index_constant = {}) { return *std::get(_children); } //! Returns the i-th child (const version). /** * \returns a const reference to the i-th child. */ template const typename Child::Type& child(index_constant = {}) const { return *std::get(_children); } //! Returns the storage of the i-th child. /** * \returns a copy of the object storing the i-th child. */ template typename Child::Storage childStorage(index_constant = {}) { return std::get(_children); } //! Returns the storage of the i-th child (const version). /** * This method is only important if the child is stored as * some kind of pointer, as this allows the pointee type to * become const. * \returns a copy of the object storing the i-th child. */ template typename Child::ConstStorage childStorage(index_constant = {}) const { return std::get(_children); } //! Sets the i-th child to the passed-in value. template void setChild(typename Child::Type& child, index_constant = {}) { std::get(_children) = stackobject_to_shared_ptr(child); } //! Store the passed value in k-th child. template void setChild(typename Child::Type&& child, index_constant = {}) { std::get(_children) = convert_arg(std::move(child)); } //! Sets the storage of the i-th child to the passed-in value. template void setChild(typename Child::Storage child, index_constant = {}) { std::get(_children) = child; } const NodeStorage& nodeStorage() const { return _children; } //! @} //! @name Nested Child Access //! @{ // The following two methods require a little bit of SFINAE trickery to work correctly: // We have to make sure that they don't shadow the methods for direct child access because // those get called by the generic child() machinery. If that machinery picks up the methods // defined below, we have an infinite recursion. // So the methods make sure that either // // * there are more than one argument. In that case, we got multiple indices and can forward // to the general machine. // // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant. // The argument thus has to be some kind of TreePath instance that we can also pass to the // generic machine. // // The above SFINAE logic works, but there is still a problem with the return type deduction. // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return // type deduction will trigger the infinite recursion. //! Returns the child given by the list of indices. /** * This method simply forwards to the freestanding function child(). See that * function for further information. */ #ifdef DOXYGEN template ImplementationDefined& child(Indices... indices) #else template auto child(I0 i0, I... i) -> typename std::enable_if< (sizeof...(I) > 0) || !is_flat_index{}, impl::_lazy_member_child_decltype >::type::template evaluate::type #endif { static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}), "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead." ); return Dune::TypeTree::child(*this,i0,i...); } //! Returns the child given by the list of indices. /** * This method simply forwards to the freestanding function child(). See that * function for further information. */ #ifdef DOXYGEN template const ImplementationDefined& child(Indices... indices) #else template auto child(I0 i0, I... i) const -> typename std::enable_if< (sizeof...(I) > 0) || !is_flat_index{}, impl::_lazy_member_child_decltype >::type::template evaluate::type #endif { static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}), "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead." ); return Dune::TypeTree::child(*this,i0,i...); } //! @} protected: //! @name Constructors //! @{ //! Default constructor. /** * This constructor requires the storage type to be default * constructible. * \warning If the storage type is a pointer, the resulting object * will not be usable before its children are set using any of the * setChild(...) methods! */ CompositeNode() {} //! Initialize all children with the passed-in objects. template::type> CompositeNode(Args&&... args) : _children(convert_arg(std::forward(args))...) {} //! Initialize the CompositeNode with copies of the passed in Storage objects. CompositeNode(std::shared_ptr... children) : _children(children...) {} //! Initialize the CompositeNode with a copy of the passed-in storage type. CompositeNode(const NodeStorage& children) : _children(children) {} //! @} private: NodeStorage _children; }; //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_COMPOSITENODE_HH dune-typetree-2.5.0/dune/typetree/exceptions.hh000066400000000000000000000007641302546717000216220ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_EXCEPTIONS_HH #define DUNE_TYPETREE_EXCEPTIONS_HH #include /** * \file * \brief TypeTree-specific exceptions. */ namespace Dune { namespace TypeTree { //! Base class for all TypeTree exceptions. class Exception : public Dune::Exception {}; } // namespace TypeTree } // namespace Dune #endif // DUNE_TYPETREE_EXCEPTIONS_HH dune-typetree-2.5.0/dune/typetree/filteredcompositenode.hh000066400000000000000000000202261302546717000240230ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_FILTEREDCOMPOSITENODE_HH #define DUNE_TYPETREE_FILTEREDCOMPOSITENODE_HH #include #include #include #include #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ #ifndef DOXYGEN namespace { // ******************************************************************************** // Utility structs for filter construction and application // ******************************************************************************** // Gets the filter and wraps it in case of a SimpleFilter. template struct get_filter; // Helper struct to extract the child template parameter pack from the ChildTypes tuple. template struct apply_filter_wrapper; template struct apply_filter_wrapper > : public Filter::template apply {}; // specialization for SimpleFilter template struct get_filter { struct type { template struct apply : public apply_filter_wrapper,Node,ChildTypes> {}; }; }; // specialization for AdvancedFilter template struct get_filter { struct type { template struct apply : public apply_filter_wrapper {}; }; }; } // anonymous namespace #endif // DOXYGEN //! Base class for composite nodes representing a filtered view on an underlying composite node. template class FilteredCompositeNode { typedef typename get_filter::type filter; typedef typename filter::template apply::type filter_result; typedef typename filter_result::template apply mapped_children; static const bool nodeIsConst = std::is_const::type>::value; template struct lazy_enable { static const bool value = !nodeIsConst; }; public: //! The type tag that describes a CompositeNode. typedef CompositeNodeTag NodeTag; //! The type used for storing the children. typedef typename mapped_children::NodeStorage NodeStorage; //! A tuple storing the types of all children. typedef typename mapped_children::ChildTypes ChildTypes; //! Mark this class as non leaf in the \ref TypeTree. static const bool isLeaf = false; //! Mark this class as a non power in the \ref TypeTree. static const bool isPower = false; //! Mark this class as a composite in the \ref TypeTree. static const bool isComposite = true; //! The number of children. static const std::size_t CHILDREN = filter_result::size; static constexpr std::size_t degree() { return filter_result::size; } //! Access to the type and storage type of the i-th child. template struct Child { #ifndef DOXYGEN typedef typename std::tuple_element::type OriginalChild; static const std::size_t mapped_index = std::tuple_element::type::original_index; #endif // DOXYGEN //! The type of the child. typedef typename OriginalChild::Type Type; //! The type of the child. typedef typename OriginalChild::type type; //! The storage type of the child. typedef typename OriginalChild::Storage Storage; //! The const storage type of the child. typedef typename OriginalChild::ConstStorage ConstStorage; }; //! @name Child Access //! @{ //! Returns the i-th child. /** * \returns a reference to the i-th child. */ template typename std::enable_if::value,typename Child::Type&>::type child() { return _node->template child::mapped_index>(); } //! Returns the i-th child (const version). /** * \returns a const reference to the i-th child. */ template const typename Child::Type& child() const { return _node->template child::mapped_index>(); } //! Returns the storage of the i-th child. /** * \returns a copy of the object storing the i-th child. */ template typename std::enable_if::value,typename Child::Storage>::type childStorage() { return _node->template childStorage::mapped_index>(); } //! Returns the storage of the i-th child (const version). /** * This method is only important if the child is stored as * some kind of pointer, as this allows the pointee type to * become const. * \returns a copy of the object storing the i-th child. */ template typename Child::ConstStorage childStorage() const { return _node->template childStorage::mapped_index>(); } //! Sets the i-th child to the passed-in value. template void setChild(typename Child::type& child, typename std::enable_if::value,void*>::type = 0) { _node->template childStorage::mapped_index>() = stackobject_to_shared_ptr(child); } //! Sets the storage of the i-th child to the passed-in value. template void setChild(typename Child::storage_type child, typename std::enable_if::value,void*>::type = 0) { _node->template childStorage::mapped_index>() = child; } //! @} //! @name Access to unfiltered node //! @{ protected: //! Returns the unfiltered node. /** * \returns A reference to the original, unfiltered node. */ template typename std::enable_if::type unfiltered() { return *_node; } //! Returns the unfiltered node (const version). /** * \returns A const reference to the original, unfiltered node. */ const Node& unfiltered() const { return *_node; } //! Returns the storage object of the unfiltered node. /** * \returns A shared_ptr to the original, unfiltered node. */ template typename std::enable_if >::type unfilteredStorage() { return _node; } //! Returns the storage object of the unfiltered node (const version). /** * \returns A shared_ptr to the original, unfiltered node. */ std::shared_ptr unfilteredStorage() const { return _node; } //! @} public: //! @name Constructors //! @{ //! Initialize the CompositeNode with copies of the passed in Storage objects. FilteredCompositeNode(std::shared_ptr node) : _node(node) {} //! Initialize the CompositeNode with a copy of the passed-in storage type. FilteredCompositeNode(Node& node) : _node(stackobject_to_shared_ptr(node)) {} //! @} private: std::shared_ptr _node; }; //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_FILTEREDCOMPOSITENODE_HH dune-typetree-2.5.0/dune/typetree/filters.hh000066400000000000000000000157061302546717000211130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_FILTERS_HH #define DUNE_TYPETREE_FILTERS_HH #include #include namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ //! A filter entry describing the mapping of one child in the filtered node. template struct FilterEntry { #ifndef DOXYGEN // The precise contents of this class is an implementation detail. static const std::size_t filtered_index = new_k; static const std::size_t original_index = old_k; #endif // DOXYGEN }; //! The result of a filter. template struct FilterResult { static const std::size_t size = sizeof...(FilterEntries); typedef std::tuple IndexMap; template struct apply { typedef std::tuple...> Children; typedef std::tuple::Type...> ChildTypes; typedef std::tuple::Storage...> NodeStorage; }; }; //! Tag describing a simple filter that can only decide whether or not to include a single given child. struct SimpleFilterTag {}; //! Tag describing an advanced filter that has full control over the construction of the list of FilterEntries. struct AdvancedFilterTag {}; //! Base class for advanced filters. struct AdvancedFilter { //! Filter tag for deciding on filter application mechanism. typedef AdvancedFilterTag FilterTag; #ifdef DOXYGEN //! Apply this filter to the given node and children template struct apply { //! The result of the filtering process. /** * This type must be a model of FilterResult. */ typedef implementation-defined type; }; #endif // DOXYGEN }; //! Default simple filter that accepts any node and leaves its child structure unchanged. /** * This default filter causes the filtered node to be exactly identical to the original node. * It is useful as a base class for documentation purposes and if you do not need to validate * the filter, as it saves having to implement the validate template struct. */ struct SimpleFilter { //! Filter tag for deciding on filter application mechanism. typedef SimpleFilterTag FilterTag; //! Validates the combination of filter and node. template struct validate { //! True if the combination of filter and node is valid. static const bool value = true; }; //! Applies the filter to the given child node. /** * This struct applies the filter to the given child to decide whether or not it will be * included in the filtered node. * * \tparam Child The type of the child node. * \tparam new_index The index this child would receive in the filtered node. * \tparam old_index The index of this child in the unfiltered node. */ template struct apply { //! True if the child will be included in the filtered node. static const bool value = true; }; }; namespace { // ******************************************************************************** // IndexFilter helpers // ******************************************************************************** template struct index_filter_helper { template struct apply { typedef FilterResult type; }; }; template struct index_filter_helper { template struct apply : public index_filter_helper::template apply > {}; }; } // anonymous namespace //! Filter class for FilteredCompositeNode that selects the children with the given indices. template struct IndexFilter : public AdvancedFilter { #ifndef DOXYGEN template struct apply { typedef typename index_filter_helper::template apply<>::type type; }; #endif // DOXYGEN }; // ******************************************************************************** // filter: Wrapper class for turning a simple filter into an advanced filter // usable by FilteredCompositeNode // ******************************************************************************** namespace { template struct filter_helper { template struct apply { typedef FilterResult type; }; }; template struct filter_helper { template struct apply : public std::conditional::value, typename filter_helper::template apply >, typename filter_helper::template apply >::type {}; }; } // anonymous namespace //! Adapter class that takes a SimpleFilter, validated it and turns it into an AdvancedFilter. template struct filter { //! Apply the filter. template struct apply { static_assert((Filter::template validate::value),"Invalid simple filter"); typedef typename filter_helper::template apply<>::type type; }; }; //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_FILTERS_HH dune-typetree-2.5.0/dune/typetree/fixedcapacitystack.hh000066400000000000000000000054751302546717000233100ustar00rootroot00000000000000// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=8 sw=2 sts=2: #ifndef DUNE_TYPETREE_FIXEDCAPACITYSTACK_HH #define DUNE_TYPETREE_FIXEDCAPACITYSTACK_HH #include #include namespace Dune { namespace TypeTree { //! \addtogroup TreePath //! \ingroup TypeTree //! \{ template class FixedCapacityStackView { public: struct Impl { Impl(T* data, std::size_t capacity) : _data(data) , _size(0) , _capacity(capacity) {} T * const _data; std::size_t _size; const std::size_t _capacity; }; FixedCapacityStackView(Impl& impl) : _impl(impl) {} public: std::size_t size() const { return _impl._size; } std::size_t capacity() const { return _impl._capacity; } bool empty() const { return _impl._size == 0; } bool full() const { return _impl._size == _impl._capacity; } void push_back(const T& t) { assert(!full()); _impl._data[_impl._size++] = t; } void pop_back() { assert(!empty()); --_impl._size; } T& back() { assert(!empty()); return _impl._data[_impl._size-1]; } const T& back() const { assert(!empty()); return _impl._data[_impl._size-1]; } T& front() { assert(!empty()); return _impl._data[0]; } const T& front() const { assert(!empty()); return _impl._data[0]; } T& operator[](std::size_t k) { assert(k < _impl._size); return _impl._data[k]; } const T& operator[](std::size_t k) const { assert(k < _impl._size); return _impl._data[k]; } private: Impl& _impl; }; template class FixedCapacityStack : private std::array , private FixedCapacityStackView::Impl , public FixedCapacityStackView { typedef FixedCapacityStackView view_base; public: using view_base::back; using view_base::front; using view_base::size; using view_base::operator[]; FixedCapacityStack() : FixedCapacityStackView::Impl(&(static_cast&>(*this)[0]),capacity) , FixedCapacityStackView(static_cast::Impl&>(*this)) {} private: //FixedCapacityStack(const FixedCapacityStack&); FixedCapacityStack& operator=(const FixedCapacityStack&); }; //! \} group TypeTree } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_FIXEDCAPACITYSTACK_HH dune-typetree-2.5.0/dune/typetree/generictransformationdescriptors.hh000066400000000000000000000126511302546717000263240ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_GENERICTRANSFORMATIONDESCRIPTORS_HH #define DUNE_TYPETREE_GENERICTRANSFORMATIONDESCRIPTORS_HH #include #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Transformation * \ingroup TypeTree * \{ */ template struct GenericLeafNodeTransformation { static const bool recursive = false; typedef TransformedNode transformed_type; typedef std::shared_ptr transformed_storage_type; static transformed_type transform(const SourceNode& s, const Transformation& t) { return transformed_type(s,t); } static transformed_type transform(std::shared_ptr s, const Transformation& t) { return transformed_type(s,t); } static transformed_storage_type transform_storage(std::shared_ptr s, const Transformation& t) { return std::make_shared(s,t); } }; template class TransformedNodeTemplate> struct TemplatizedGenericPowerNodeTransformation { static const bool recursive = true; template struct result { typedef typename TransformedNodeTemplate::type type; typedef std::shared_ptr storage_type; static const std::size_t degree = StaticDegree::value; }; template static typename result::type transform(const SourceNode& s, const Transformation& t, const std::array,result::degree>& children) { return typename result::type(s,t,children); } template static typename result::type transform(std::shared_ptr s, const Transformation& t, const std::array,result::degree>& children) { return typename result::type(s,t,children); } template static typename result::storage_type transform_storage(std::shared_ptr s, const Transformation& t, const std::array,result::degree>& children) { return std::make_shared::type>(s,t,children); } }; template class TransformedNode> struct GenericPowerNodeTransformation : public TemplatizedGenericPowerNodeTransformation::template result > {}; template class TransformedNodeTemplate> struct TemplatizedGenericCompositeNodeTransformation { static const bool recursive = true; template struct result { typedef typename TransformedNodeTemplate::type type; typedef std::shared_ptr storage_type; }; template static typename result::type transform(const SourceNode& s, const Transformation& t, std::shared_ptr... children) { return typename result::type(s,t,children...); } template static typename result::type transform(std::shared_ptr s, const Transformation& t, std::shared_ptr... children) { return typename result::type(s,t,children...); } template static typename result::storage_type transform_storage(std::shared_ptr s, const Transformation& t, std::shared_ptr... children) { return std::make_shared::type>(s,t,children...); } }; template class TransformedNode> struct GenericCompositeNodeTransformation : public TemplatizedGenericCompositeNodeTransformation::template result > {}; //! \} group Transformation } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_GENERICTRANSFORMATIONDESCRIPTORS_HH dune-typetree-2.5.0/dune/typetree/leafnode.hh000066400000000000000000000027321302546717000212130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_LEAFNODE_HH #define DUNE_TYPETREE_LEAFNODE_HH #include #include namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ /** \brief Base class for leaf nodes in a \ref TypeTree. * * Every leaf type in a \ref TypeTree must be derived from this * class. */ class LeafNode { public: //! Mark this class as a leaf in a \ref TypeTree. static const bool isLeaf = true; //! Mark this class as a non power in the \ref TypeTree. static const bool isPower = false; //! Mark this class as a non composite in the \ref TypeTree. static const bool isComposite = false; //! Leafs have no children. static const std::size_t CHILDREN = 0; //! The type tag that describes a LeafNode. typedef LeafNodeTag NodeTag; static constexpr std::size_t degree() { return 0; } protected: //! Default constructor. /** * The default constructor is protected, as LeafNode is a utility * class that needs to be filled with meaning by subclassing it * and adding useful functionality to the subclass. */ LeafNode() {} }; //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_POWERNODE_HH dune-typetree-2.5.0/dune/typetree/nodeinterface.hh000066400000000000000000000065261302546717000222510ustar00rootroot00000000000000// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=8 sw=2 sts=2: #ifndef DUNE_TYPETREE_NODEINTERFACE_HH #define DUNE_TYPETREE_NODEINTERFACE_HH #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ /** \brief Interface for nodes in a \ref TypeTree. * * This class cannot be used itself, it is for documentation purposes * only. * * \note Constructor signatures are explicitly not specified by this * interface. * \note In addition, every node in a tree must be derived from one of * the node base classes LeafNode, PowerNode, or CompositeNode, * or from a base class for a yet-to-be-defined new node type. */ struct NodeInterface { //! Whether this is a leaf node in a \ref TypeTree. static const bool isLeaf = implementationDefined; //! Whether this is a power node in the \ref TypeTree. static const bool isPower = implementationDefined; //! Whether this is a composite node in the \ref TypeTree. static const bool isComposite = implementationDefined; //! Number of children of this node in the \ref TypeTree static const std::size_t CHILDREN = implementationDefined; //! The type tag that describes what kind of node this is /** * One of LeafNodeTag, PowerNodeTag or CompositeNodeTag. * Other tags are also possible when new * kinds of nodes are defined. */ typedef ImplementationDefined NodeTag; //! container type to pass around a collection of children /** * \note This typedef is not present for leaf nodes. */ typedef ImplementationDefined NodeStorage; }; //! Returns the node tag of the given Node. template using NodeTag = typename std::decay_t::NodeTag; //! Returns the implementation tag of the given Node. template using ImplementationTag = typename std::decay_t::ImplementationTag; //! Returns the degree of node as run time information. template std::size_t degree(const Node& node) { return degree(&node,NodeTag()); } #ifndef DOXYGEN //! Default implementation of degree dispatch function. /** * This dispatches using a pointer to the node instead of a reference, * as we can easily create a constexpr pointer to the node, while a constexpr * reference might not even be possible to manufacture (std::declval is not * constexpr). */ template constexpr std::size_t degree(const Node* node, NodeTag) { return Node::degree(); } #endif // DOXYGEN //! Returns the statically known degree of the given Node type as a std::integral_constant. /** * \note If you are only interested in the numeric value, take a look at staticDegree * instead. */ template using StaticDegree = std::integral_constant< std::size_t, degree( static_cast*>(nullptr), NodeTag>() ) >; //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_NODEINTERFACE_HH dune-typetree-2.5.0/dune/typetree/nodetags.hh000066400000000000000000000013071302546717000212370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_NODETAGS_HH #define DUNE_TYPETREE_NODETAGS_HH namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ //! Tag designating a leaf node. struct LeafNodeTag {}; //! Tag designating a power node. struct PowerNodeTag {}; //! Tag designating a composite node. struct CompositeNodeTag {}; #ifndef DOXYGEN //! Special tag used as start value in algorithms. struct StartTag {}; #endif // DOXYGEN //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_NODETAGS_HH dune-typetree-2.5.0/dune/typetree/pairtraversal.hh000066400000000000000000000152341302546717000223160ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_PAIRTRAVERSAL_HH #define DUNE_TYPETREE_PAIRTRAVERSAL_HH #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Tree Traversal * \ingroup TypeTree * \{ */ #ifndef DOXYGEN // these are all internals and not public API. Only access is using applyToTree(). template struct ApplyToTreePair { template static void apply(Node1&& node1, Node2&& node2, Visitor&& visitor) { ApplyToTreePair, NodeTag >::apply(std::forward(node1), std::forward(node2), std::forward(visitor), TreePathFactory::create(node1).mutablePath()); } }; // Do not visit nodes the visitor is not interested in template struct ApplyToTreePair { template static void apply(const Node1& node1, const Node2& node2, const Visitor& visitor, TreePath treePath) {} }; /* // LeafNode - again, this is easy: just do all three visits template struct ApplyToTree { #if HAVE_RVALUE_REFERENCES template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { v.leaf(std::forward(n1),std::forward(n2),tp.view()); } #else template static void apply(N1& n1, N2& n2, V& v, TreePath tp) { v.leaf(n1,n2,tp.view()); } template static void apply(const N1& n1, const N2& n2, V& v, TreePath tp) { v.leaf(n1,n2,tp.view()); } template static void apply(N1& n1, N2& n2, const V& v, TreePath tp) { v.leaf(n1,n2,tp.view()); } template static void apply(const N1& n1, const N2& n2, const V& v, TreePath tp) { v.leaf(n1,n2,tp.view()); } #endif // HAVE_RVALUE_REFERENCES }; */ // Automatically pick the correct traversal algorithm for the two nodes template struct ApplyToTreePair : public ApplyToGenericCompositeNodePair { }; // ******************************************************************************** // Specialization for dynamic traversal and two PowerNodes -> use runtime iteration // ******************************************************************************** template<> struct ApplyToTreePair { template static void apply(N1&& n1, N2&& n2, V&& v, TreePath tp) { v.pre(std::forward(n1),std::forward(n2),tp.view()); typedef typename std::remove_reference::type Node1; typedef typename std::remove_reference::type Node2; typedef typename Node1::template Child<0>::Type C1; typedef typename Node2::template Child<0>::Type C2; static_assert(StaticDegree::value == StaticDegree::value, "non-leaf nodes with different numbers of children " \ "are not allowed during simultaneous grid traversal"); const bool visit = std::remove_reference::type ::template VisitChild::value; for (std::size_t k = 0; k < degree(n1); ++k) { v.beforeChild(std::forward(n1),n1.child(k),std::forward(n2),n2.child(k),tp.view(),k); tp.push_back(k); ApplyToTreePair, NodeTag, visit>::apply(n1.child(k), n2.child(k), std::forward(v), tp); tp.pop_back(); v.afterChild(std::forward(n1),n1.child(k),std::forward(n2),n2.child(k),tp.view(),k); if (k < degree(n1) - 1) v.in(std::forward(n1),std::forward(n2),tp.view()); } v.post(std::forward(n1),std::forward(n2),tp.view()); } }; #endif // DOXYGEN //! Apply visitor to a pair of TypeTrees. /** * This function applies the given visitor to the given tree. Both visitor and tree may be const * or non-const. If the compiler supports rvalue references, they may even be a non-const temporary; * otherwise both trees must be either const or non-const. If they have different constness, both will * be promoted to const. * * \note The visitor must implement the interface laid out by DefaultPairVisitor (most easily achieved by * inheriting from it) and specify the required type of tree traversal (static or dynamic) by * inheriting from either StaticTraversal or DynamicTraversal. * * \param tree1 The first tree the visitor will be applied to. * \param tree2 The second tree the visitor will be applied to. * \param visitor The visitor to apply to the trees. */ template void applyToTreePair(Tree1&& tree1, Tree2&& tree2, Visitor&& visitor) { ApplyToTreePair::type::treePathType>::apply(std::forward(tree1), std::forward(tree2), std::forward(visitor)); } //! \} group Tree Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_PAIRTRAVERSAL_HH dune-typetree-2.5.0/dune/typetree/powercompositenodetransformationtemplates.hh000066400000000000000000000022701302546717000302660ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_POWERCOMPOSITENODETRANSFORMATIONTEMPLATES_HH #define DUNE_TYPETREE_POWERCOMPOSITENODETRANSFORMATIONTEMPLATES_HH #include #include namespace Dune { namespace TypeTree { /** \addtogroup Transformation * \ingroup TypeTree * \{ */ template class TransformedNode> struct GenericPowerNodeTransformationTemplate { template struct result { typedef TransformedNode::value> type; }; }; template class TransformedNode> struct GenericCompositeNodeTransformationTemplate { template struct result { typedef TransformedNode type; }; }; //! \} group Transformation } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_POWERCOMPOSITENODETRANSFORMATIONTEMPLATES_HH dune-typetree-2.5.0/dune/typetree/powernode.hh000066400000000000000000000350061302546717000214400ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_POWERNODE_HH #define DUNE_TYPETREE_POWERNODE_HH #include #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ #ifndef DOXYGEN namespace { // prototype and end of recursion template void assign_reference_pack_to_shared_ptr_array_unpack(It it, Args&&... args) {} template void assign_reference_pack_to_shared_ptr_array_unpack(It it, Arg&& arg, Args&&... args) { static_assert(std::is_same::type>::type>::value,"type mismatch during array conversion"); *it = convert_arg(std::forward(arg)); assign_reference_pack_to_shared_ptr_array_unpack(++it,std::forward(args)...); } template void assign_reference_pack_to_shared_ptr_array(std::array,n>& res, Args&&... args) { static_assert(sizeof...(Args) == n, "invalid number of arguments"); return assign_reference_pack_to_shared_ptr_array_unpack(res.begin(),std::forward(args)...); } // prototype and end of recursion template void assign_shared_ptr_pack_to_shared_ptr_array_unpack(It it, Args&&... args) {} template void assign_shared_ptr_pack_to_shared_ptr_array_unpack(It it, Arg&& arg, Args&&... args) { static_assert(std::is_same::type::element_type>::value,"type mismatch during array conversion"); *it = arg; assign_shared_ptr_pack_to_shared_ptr_array_unpack(++it,args...); } template void assign_shared_ptr_pack_to_shared_ptr_array(std::array,n>& res, Args&&... args) { static_assert(sizeof...(Args) == n, "invalid number of arguments"); return assign_shared_ptr_pack_to_shared_ptr_array_unpack(res.begin(),args...); } } // anonymous namespace #endif #ifndef DOXYGEN //! Helper struct to make constructor enabling mechanism in PowerNode more readable. template struct AssertPowerNodeChildCount : public std::enable_if::value && PowerNode::CHILDREN == k, T> {}; #endif /** \brief Collect k instances of type T within a \ref TypeTree. * * \tparam T The base type * \tparam k The number of instances this node should collect */ template class PowerNode { public: //! Mark this class as non leaf in the \ref TypeTree. static const bool isLeaf = false; //! Mark this class as a power in the \ref TypeTree. static const bool isPower = true; //! Mark this class as a non composite in the \ref TypeTree. static const bool isComposite = false; //! The number of children. static const std::size_t CHILDREN = k; static constexpr std::size_t degree() { return k; } //! The type tag that describes a PowerNode. typedef PowerNodeTag NodeTag; //! The type of each child. typedef T ChildType; //! The storage type of each child. typedef shared_ptr ChildStorageType; //! The const version of the storage type of each child. typedef shared_ptr ChildConstStorageType; //! The type used for storing the children. typedef std::array NodeStorage; //! Access to the type and storage type of the i-th child. template struct Child { static_assert((i < CHILDREN), "child index out of range"); //! The type of the child. typedef T Type; //! The type of the child. typedef T type; //! The storage type of the child. typedef ChildStorageType Storage; //! The const storage type of the child. typedef ChildConstStorageType ConstStorage; }; //! @name Child Access (templated methods) //! @{ //! Returns the i-th child. /** * \returns a reference to the i-th child. */ template T& child (index_constant = {}) { static_assert((i < CHILDREN), "child index out of range"); return *_children[i]; } //! Returns the i-th child (const version). /** * \returns a const reference to the i-th child. */ template const T& child (index_constant = {}) const { static_assert((i < CHILDREN), "child index out of range"); return *_children[i]; } //! Returns the storage of the i-th child. /** * \returns a copy of the object storing the i-th child. */ template ChildStorageType childStorage(index_constant = {}) { static_assert((i < CHILDREN), "child index out of range"); return _children[i]; } //! Returns the storage of the i-th child (const version). /** * This method is only important if the child is stored as * some kind of pointer, as this allows the pointee type to * become const. * \returns a copy of the object storing the i-th child. */ template ChildConstStorageType childStorage(index_constant = {}) const { static_assert((i < CHILDREN), "child index out of range"); return _children[i]; } //! Sets the i-th child to the passed-in value. template void setChild (T& t, index_constant = {}) { static_assert((i < CHILDREN), "child index out of range"); _children[i] = stackobject_to_shared_ptr(t); } //! Store the passed value in i-th child. template void setChild(T&& t, index_constant = {}) { static_assert((i < CHILDREN), "child index out of range"); _children[i] = convert_arg(std::move(t)); } //! Sets the stored value representing the i-th child to the passed-in value. template void setChild (ChildStorageType st, index_constant = {}) { static_assert((i < CHILDREN), "child index out of range"); _children[i] = st; } //! @} //! @name Child Access (Dynamic methods) //! @{ //! Returns the i-th child. /** * \returns a reference to the i-th child. */ T& child (std::size_t i) { assert(i < CHILDREN && "child index out of range"); return *_children[i]; } //! Returns the i-th child (const version). /** * \returns a const reference to the i-th child. */ const T& child (std::size_t i) const { assert(i < CHILDREN && "child index out of range"); return *_children[i]; } //! Returns the storage of the i-th child. /** * \returns a copy of the object storing the i-th child. */ ChildStorageType childStorage(std::size_t i) { assert(i < CHILDREN && "child index out of range"); return _children[i]; } //! Returns the storage of the i-th child (const version). /** * This method is only important if the child is stored as * some kind of pointer, as this allows the pointee type to * become const. * \returns a copy of the object storing the i-th child. */ ChildConstStorageType childStorage (std::size_t i) const { assert(i < CHILDREN && "child index out of range"); return (_children[i]); } //! Sets the i-th child to the passed-in value. void setChild (std::size_t i, T& t) { assert(i < CHILDREN && "child index out of range"); _children[i] = stackobject_to_shared_ptr(t); } //! Store the passed value in i-th child. void setChild(std::size_t i, T&& t) { assert(i < CHILDREN && "child index out of range"); _children[i] = convert_arg(std::move(t)); } //! Sets the stored value representing the i-th child to the passed-in value. void setChild (std::size_t i, ChildStorageType st) { assert(i < CHILDREN && "child index out of range"); _children[i] = st; } const NodeStorage& nodeStorage() const { return _children; } //! @} //! @name Nested Child Access //! @{ // The following two methods require a little bit of SFINAE trickery to work correctly: // We have to make sure that they don't shadow the methods for direct child access because // those get called by the generic child() machinery. If that machinery picks up the methods // defined below, we have an infinite recursion. // So the methods make sure that either // // * there are more than one argument. In that case, we got multiple indices and can forward // to the general machine. // // * the first argument is not a valid flat index, i.e. either a std::size_t or an index_constant. // The argument thus has to be some kind of TreePath instance that we can also pass to the // generic machine. // // The above SFINAE logic works, but there is still a problem with the return type deduction. // We have to do a lazy lookup of the return type after SFINAE has succeeded, otherwise the return // type deduction will trigger the infinite recursion. //! Returns the child given by the list of indices. /** * This method simply forwards to the freestanding function child(). See that * function for further information. */ #ifdef DOXYGEN template ImplementationDefined& child(Indices... indices) #else template auto child(I0 i0, I... i) -> typename std::enable_if< (sizeof...(I) > 0) || !is_flat_index{}, impl::_lazy_member_child_decltype >::type::template evaluate::type #endif { static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}), "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead." ); return Dune::TypeTree::child(*this,i0,i...); } //! Returns the child given by the list of indices. /** * This method simply forwards to the freestanding function child(). See that * function for further information. */ #ifdef DOXYGEN template const ImplementationDefined& child(Indices... indices) #else template auto child(I0 i0, I... i) const -> typename std::enable_if< (sizeof...(I) > 0) || !is_flat_index{}, impl::_lazy_member_child_decltype >::type::template evaluate::type #endif { static_assert(sizeof...(I) > 0 || impl::_non_empty_tree_path(I0{}), "You cannot use the member function child() with an empty TreePath, use the freestanding version child(node,treePath) instead." ); return Dune::TypeTree::child(*this,i0,i...); } //! @} //! @name Constructors //! @{ protected: //! Default constructor. /** * The default constructor is protected, as PowerNode is a utility * class that needs to be filled with meaning by subclassing it * and adding useful functionality to the subclass. * * \warning When using the default constructor, make sure to set ALL children * by means of the setChild() methods! */ PowerNode() {} //! Initialize the PowerNode with a copy of the passed-in storage type. explicit PowerNode(const NodeStorage& children) : _children(children) {} //! Initialize all children with copies of a storage object constructed from the parameter \c t. explicit PowerNode (T& t, bool distinct_objects = true) { if (distinct_objects) { for (typename NodeStorage::iterator it = _children.begin(); it != _children.end(); ++it) *it = std::make_shared(t); } else { shared_ptr sp = stackobject_to_shared_ptr(t); std::fill(_children.begin(),_children.end(),sp); } } #ifdef DOXYGEN //! Initialize all children with the passed-in objects. /** * The availability of this constructor depends on the number of children and * compiler support for C++0x: For 1 <= k <= 10, it is always present, but for * k > 10, it requires C++0x support in the compiler. If your compiler doesn't, * use PowerNode(const Storage& children) instead. * * Moreover, the C++0x-based version also supports passing in temporary objects * and will move those objects into the node. Attempting to do so with the legacy * version will result in a compile error. */ PowerNode(T& t1, T& t2, ...) {} #else // this weird signature avoids shadowing other 1-argument constructors template PowerNode (C0&& c0, C1&& c1, Children&&... children) { assign_reference_pack_to_shared_ptr_array(_children,std::forward(c0),std::forward(c1),std::forward(children)...); } // this weird signature avoids shadowing other 1-argument constructors template PowerNode (shared_ptr c0, shared_ptr c1, shared_ptr... children) { assign_shared_ptr_pack_to_shared_ptr_array(_children,c0,c1,children...); } #endif // DOXYGEN //! @} private: NodeStorage _children; }; //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_POWERNODE_HH dune-typetree-2.5.0/dune/typetree/proxynode.hh000066400000000000000000000233771302546717000214750ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_PROXYNODE_HH #define DUNE_TYPETREE_PROXYNODE_HH #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Nodes * \ingroup TypeTree * \{ */ template class ProxyNode; //! Mixin class providing methods for child access with compile-time parameter. template class StaticChildAccessors { static const bool proxiedNodeIsConst = std::is_const::type>::value; template struct lazy_enabled { static const bool value = !proxiedNodeIsConst; }; typedef ProxyNode Node; template typename std::enable_if::type node() { return static_cast(*this); } const Node& node() const { return static_cast(*this); } public: //! Access to the type and storage type of the i-th child. template struct Child : public ProxiedNode::template Child {}; //! @name Child Access //! @{ //! Returns the i-th child. /** * \returns a reference to the i-th child. */ template typename std::enable_if::value,typename Child::Type&>::type child() { return node().proxiedNode().template child(); } //! Returns the i-th child (const version). /** * \returns a const reference to the i-th child. */ template const typename Child::Type& child() const { return node().proxiedNode().template child(); } //! Returns the storage of the i-th child. /** * \returns a copy of the object storing the i-th child. */ template typename std::enable_if::value,typename Child::Storage>::type childStorage() { return node().proxiedNode().template childStorage(); } //! Returns the storage of the i-th child (const version). /** * This method is only important if the child is stored as * some kind of pointer, as this allows the pointee type to * become const. * \returns a copy of the object storing the i-th child. */ template typename Child::ConstStorage childStorage() const { return node().proxiedNode().template childStorage(); } //! Sets the i-th child to the passed-in value. template void setChild(typename Child::type& child, typename std::enable_if::value,void*>::type = 0) { node().proxiedNode().template childStorage() = stackobject_to_shared_ptr(child); } //! Sets the storage of the i-th child to the passed-in value. template void setChild(typename Child::storage_type child, typename std::enable_if::value,void*>::type = 0) { node().proxiedNode().template childStorage() = child; } const typename ProxiedNode::NodeStorage& nodeStorage() const { return node().proxiedNode().nodeStorage(); } }; //! Mixin class providing methods for child access with run-time parameter. /** * This class also provides the compile-time parameter based methods, as * multiple inheritance from both DynamicChildAccessors and StaticChildAccessors * creates ambigous method lookups. */ template class DynamicChildAccessors : public StaticChildAccessors { typedef ProxyNode Node; static const bool proxiedNodeIsConst = std::is_const::type>::value; template typename std::enable_if::type node() { return static_cast(*this); } const Node& node() const { return static_cast(*this); } public: //! @name Child Access (Dynamic methods) //! @{ //! Returns the i-th child. /** * \returns a reference to the i-th child. */ template typename std::enable_if::type child (std::size_t i) { return node().proxiedNode().child(i); } //! Returns the i-th child (const version). /** * \returns a const reference to the i-th child. */ const typename ProxiedNode::ChildType& child (std::size_t i) const { return node().proxiedNode().child(i); } //! Returns the storage of the i-th child. /** * \returns a copy of the object storing the i-th child. */ template typename std::enable_if::type childStorage(std::size_t i) { return node().proxiedNode().childStorage(i); } //! Returns the storage of the i-th child (const version). /** * This method is only important if the child is stored as * some kind of pointer, as this allows the pointee type to * become const. * \returns a copy of the object storing the i-th child. */ typename ProxiedNode::ChildConstStorageType childStorage (std::size_t i) const { return node().proxiedNode().childStorage(i); } //! Sets the i-th child to the passed-in value. template void setChild (std::size_t i, typename ProxiedNode::ChildType& t, typename std::enable_if::type = 0) { node().proxiedNode().childStorage(i) = stackobject_to_shared_ptr(t); } //! Sets the stored value representing the i-th child to the passed-in value. template void setChild (std::size_t i, typename ProxiedNode::ChildStorageType st, typename std::enable_if::type = 0) { node().proxiedNode().childStorage(i) = st; } }; //! Tag-based dispatch to appropriate base class that provides necessary functionality. template struct ProxyNodeBase; //! ProxyNode base class for LeafNode. template struct ProxyNodeBase { }; //! ProxyNode base class for CompositeNode. template struct ProxyNodeBase : public StaticChildAccessors { typedef typename Node::ChildTypes ChildTypes; typedef typename Node::NodeStorage NodeStorage; }; //! ProxyNode base class for PowerNode. template struct ProxyNodeBase : public DynamicChildAccessors { typedef typename Node::ChildType ChildType; typedef typename Node::NodeStorage NodeStorage; }; //! Base class for nodes acting as a proxy for an existing node. /** * ProxyNode is a utility class for implementing proxy classes * that need to provide the TypeTree node functionality of the * proxied class. It exactly mirrors the TypeTree node characteristics * of the proxied node. */ template class ProxyNode : public ProxyNodeBase> { static const bool proxiedNodeIsConst = std::is_const::type>::value; // accessor mixins need to be friends for access to proxiedNode() friend class StaticChildAccessors; friend class DynamicChildAccessors; public: typedef Node ProxiedNode; typedef Dune::TypeTree::NodeTag NodeTag; //! Mark this class as non leaf in the \ref TypeTree. static const bool isLeaf = Node::isLeaf; //! Mark this class as a non power in the \ref TypeTree. static const bool isPower = Node::isPower; //! Mark this class as a composite in the \ref TypeTree. static const bool isComposite = Node::isComposite; //! The number of children. static const std::size_t CHILDREN = StaticDegree::value; static constexpr std::size_t degree() { return StaticDegree::value; } protected: //! @name Access to the proxied node //! @{ //! Returns the proxied node. template typename std::enable_if::type proxiedNode() { return *_node; } //! Returns the proxied node (const version). const Node& proxiedNode() const { return *_node; } //! Returns the storage of the proxied node. template typename std::enable_if >::type proxiedNodeStorage() { return _node; } //! Returns the storage of the proxied node (const version). shared_ptr proxiedNodeStorage() const { return _node; } //! @} //! @name Constructors //! @{ ProxyNode(Node& node) : _node(stackobject_to_shared_ptr(node)) {} ProxyNode(shared_ptr node) : _node(node) {} //! @} private: shared_ptr _node; }; //! \} group Nodes } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_PROXYNODE_HH dune-typetree-2.5.0/dune/typetree/simpletransformationdescriptors.hh000066400000000000000000000062121302546717000261750ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_SIMPLETRANSFORMATIONDESCRIPTORS_HH #define DUNE_TYPETREE_SIMPLETRANSFORMATIONDESCRIPTORS_HH #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Transformation * \ingroup TypeTree * \{ */ template struct SimpleLeafNodeTransformation { static const bool recursive = false; typedef TransformedNode transformed_type; typedef std::shared_ptr transformed_storage_type; static transformed_type transform(const SourceNode& s, const Transformation& t) { return transformed_type(); } static transformed_storage_type transform_storage(std::shared_ptr s, const Transformation& t) { return std::make_shared(); } }; template class TransformedNode> struct SimplePowerNodeTransformation { static const bool recursive = true; template struct result { typedef TransformedNode::value> type; typedef std::shared_ptr storage_type; static const std::size_t degree = StaticDegree::value; }; template static typename result::type transform(const SourceNode& s, const Transformation& t, const std::array,result::degree>& children) { return typename result::type(children); } template static typename result::storage_type transform_storage(std::shared_ptr s, const Transformation& t, const std::array,result::degree>& children) { return std::make_shared::type>(children); } }; template class TransformedNode> struct SimpleCompositeNodeTransformation { static const bool recursive = true; template struct result { typedef TransformedNode type; typedef std::shared_ptr storage_type; }; template static typename result::type transform(const SourceNode& s, const Transformation& t, std::shared_ptr... children) { return typename result::type(children...); } template static typename result::storage_type transform_storage(std::shared_ptr s, const Transformation& t, std::shared_ptr... children) { return std::make_shared::type>(children...); } }; //! \} group Transformation } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_SIMPLETRANSFORMATIONDESCRIPTORS_HH dune-typetree-2.5.0/dune/typetree/transformation.hh000066400000000000000000000544711302546717000225130ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_TRANSFORMATION_HH #define DUNE_TYPETREE_TRANSFORMATION_HH #include #include #include #include #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Transformation * \ingroup TypeTree * \{ */ #ifdef DOXYGEN //! Register transformation descriptor to transform SourceNode with Transformation. /** * The tree transformation engine expects this function to return a struct describing * how to perform the Transformation for The type SourceNode, which has ImplementationTag Tag. * This function has to be specialized for every combination of Transformation and Tag that * the transformation engine should support. * * \note The arguments are given as pointers to avoid problems with incomplete types. * * \note The specialization does not have to placed in the namespace Dune::TypeTree, * it can simply reside in the same namespace as either the SourceNode or the Tag. * * \note This function will never be really called, the engine only extracts the return type. * It is thus not necessary to actually implement the function, it is sufficient to * declare it. * * \tparam SourceNode The type of the node in the source tree that should be transformed. * \tparam Transformation The type of the transformation to apply to the source node. * \tparam Tag The implementation tag of the source node. */ template void registerNodeTransformation(SourceNode*, Transformation*, Tag*); #else // DOXYGEN /** * \tparam S C++ type of source node. * \tparam T Tag identifying the transformation. * \tparam Tag Tag identifying the source type. * * Tag may be identical for different implementation of the same concept * (i.e. all leaf GridFunctionSpace), but this is not required. This * allows you to handle different leaf GridFunctionSpace implementation * differently. Tag should be extracted from S::ImplementationTag. */ template struct LookupNodeTransformation { typedef decltype(registerNodeTransformation(declptr(),declptr(),declptr())) lookup_type; typedef typename evaluate_if_meta_function< lookup_type >::type type; static_assert((!std::is_same::value), "Unable to find valid transformation descriptor"); }; #endif // DOXYGEN //! Transform a TypeTree. /** * This struct can be used to apply a transformation to a given TypeTree. It exports the type of * the resulting (transformed) tree and contains methods to actually transform tree instances. * * \tparam SourceTree = The TypeTree that should be transformed. * \tparam Transformation = The Transformation to apply to the TypeTree. * \tparam Tag = This parameter is an implementation detail and must always be set to its default value. * \tparam recursive = This parameter is an implementation detail and must always be set to its default value. */ template struct TransformTree { #ifndef DOXYGEN typedef typename LookupNodeTransformation::type NodeTransformation; // the type of the new tree that will result from this transformation typedef typename TransformTree,NodeTransformation::recursive>::transformed_type transformed_type; // the storage type of the new tree that will result from this transformation typedef typename TransformTree,NodeTransformation::recursive>::transformed_storage_type transformed_storage_type; #endif // DOXYGEN //! The type of the transformed tree. typedef transformed_type type; typedef type Type; //! Apply transformation to an existing tree s. static transformed_type transform(const SourceTree& s, const Transformation& t = Transformation()) { return TransformTree,NodeTransformation::recursive>::transform(s,t); } //! Apply transformation to an existing tree s. static transformed_type transform(const SourceTree& s, Transformation& t) { return TransformTree,NodeTransformation::recursive>::transform(s,t); } //! Apply transformation to an existing tree s. static transformed_type transform(std::shared_ptr sp, const Transformation& t = Transformation()) { return TransformTree,NodeTransformation::recursive>::transform(sp,t); } //! Apply transformation to an existing tree s. static transformed_type transform(std::shared_ptr sp, Transformation& t) { return TransformTree,NodeTransformation::recursive>::transform(sp,t); } //! Apply transformation to storage type of an existing tree, returning a heap-allocated storage type //! instance of the transformed tree. static transformed_storage_type transform_storage(std::shared_ptr sp, const Transformation& t = Transformation()) { return TransformTree,NodeTransformation::recursive>::transform_storage(sp,t); } //! Apply transformation to storage type of an existing tree, returning a heap-allocated storage type //! instance of the transformed tree. static transformed_storage_type transform_storage(std::shared_ptr sp, Transformation& t) { return TransformTree,NodeTransformation::recursive>::transform_storage(sp,t); } }; #ifndef DOXYGEN // internal per-node implementations of the transformation algorithm // handle a leaf node - this is easy template struct TransformTree { // get transformed type from specification typedef typename LookupNodeTransformation>::type NodeTransformation; typedef typename NodeTransformation::transformed_type transformed_type; typedef typename NodeTransformation::transformed_storage_type transformed_storage_type; // delegate instance transformation to per-node specification static transformed_type transform(const S& s, T& t) { return NodeTransformation::transform(s,t); } // delegate instance transformation to per-node specification static transformed_type transform(const S& s, const T& t) { return NodeTransformation::transform(s,t); } // delegate instance transformation to per-node specification static transformed_type transform(std::shared_ptr sp, T& t) { return NodeTransformation::transform(sp,t); } // delegate instance transformation to per-node specification static transformed_type transform(std::shared_ptr sp, const T& t) { return NodeTransformation::transform(sp,t); } static transformed_storage_type transform_storage(std::shared_ptr sp, T& t) { return NodeTransformation::transform_storage(sp,t); } static transformed_storage_type transform_storage(std::shared_ptr sp, const T& t) { return NodeTransformation::transform_storage(sp,t); } }; // common implementation for non-recursive transformation of non-leaf nodes template struct TransformTreeNonRecursive { // get transformed type from specification typedef typename LookupNodeTransformation>::type NodeTransformation; typedef typename NodeTransformation::transformed_type transformed_type; typedef typename NodeTransformation::transformed_storage_type transformed_storage_type; // delegate instance transformation to per-node specification static transformed_type transform(const S& s, T& t) { return NodeTransformation::transform(s,t); } // delegate instance transformation to per-node specification static transformed_type transform(const S& s, const T& t) { return NodeTransformation::transform(s,t); } // delegate instance transformation to per-node specification static transformed_type transform(std::shared_ptr sp, T& t) { return NodeTransformation::transform(sp,t); } // delegate instance transformation to per-node specification static transformed_type transform(std::shared_ptr sp, const T& t) { return NodeTransformation::transform(sp,t); } static transformed_storage_type transform_storage(std::shared_ptr sp, T& t) { return NodeTransformation::transform_storage(sp,t); } static transformed_storage_type transform_storage(std::shared_ptr sp, const T& t) { return NodeTransformation::transform_storage(sp,t); } }; // handle power tag - a little more tricky template struct TransformTree { // get transformed type from specification // Handling this transformation in a way that makes the per-node specification easy to write // is a little involved: // The problem is that the transformed power node must be parameterized on the transformed child // type. So we need to transform the child type and pass the transformed child type to an inner // template of the node transformation struct called result (see example of such a specification // further down). typedef typename LookupNodeTransformation>::type NodeTransformation; typedef typename LookupNodeTransformation>::type ChildNodeTransformation; typedef typename NodeTransformation::template result, ChildNodeTransformation::recursive>::transformed_type >::type transformed_type; typedef typename NodeTransformation::template result, ChildNodeTransformation::recursive>::transformed_type >::storage_type transformed_storage_type; // Transform an instance of S. static transformed_type transform(const S& s, T& t) { // transform children typedef TransformTree,ChildNodeTransformation::recursive> ChildTreeTransformation; typedef typename ChildTreeTransformation::transformed_type transformed_child; const std::size_t child_count = StaticDegree::value; std::array,child_count> children; for (std::size_t k = 0; k < child_count; ++k) { children[k] = ChildTreeTransformation::transform_storage(s.childStorage(k),t); } // transform node return NodeTransformation::transform(s,t,children); } static transformed_type transform(const S& s, const T& t) { // transform children typedef TransformTree,ChildNodeTransformation::recursive> ChildTreeTransformation; typedef typename ChildTreeTransformation::transformed_type transformed_child; const std::size_t child_count = StaticDegree::value; std::array,child_count> children; for (std::size_t k = 0; k < child_count; ++k) { children[k] = ChildTreeTransformation::transform_storage(s.childStorage(k),t); } // transform node return NodeTransformation::transform(s,t,children); } // Transform an instance of S. static transformed_type transform(std::shared_ptr sp, T& t) { // transform children typedef TransformTree,ChildNodeTransformation::recursive> ChildTreeTransformation; typedef typename ChildTreeTransformation::transformed_type transformed_child; const std::size_t child_count = StaticDegree::value; std::array,child_count> children; for (std::size_t k = 0; k < child_count; ++k) { children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t); } // transform node return NodeTransformation::transform(sp,t,children); } static transformed_type transform(std::shared_ptr sp, const T& t) { // transform children typedef TransformTree,ChildNodeTransformation::recursive> ChildTreeTransformation; typedef typename ChildTreeTransformation::transformed_type transformed_child; const std::size_t child_count = StaticDegree::value; std::array,child_count> children; for (std::size_t k = 0; k < child_count; ++k) { children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t); } // transform node return NodeTransformation::transform(sp,t,children); } static transformed_storage_type transform_storage(std::shared_ptr sp, T& t) { // transform children typedef TransformTree,ChildNodeTransformation::recursive> ChildTreeTransformation; typedef typename ChildTreeTransformation::transformed_storage_type transformed_child_storage; const std::size_t child_count = StaticDegree::value; std::array children; for (std::size_t k = 0; k < child_count; ++k) { children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t); } return NodeTransformation::transform_storage(sp,t,children); } static transformed_storage_type transform_storage(std::shared_ptr sp, const T& t) { // transform children typedef TransformTree,ChildNodeTransformation::recursive> ChildTreeTransformation; typedef typename ChildTreeTransformation::transformed_storage_type transformed_child_storage; const std::size_t child_count = StaticDegree::value; std::array children; for (std::size_t k = 0; k < child_count; ++k) { children[k] = ChildTreeTransformation::transform_storage(sp->childStorage(k),t); } return NodeTransformation::transform_storage(sp,t,children); } }; // non-recursive version of the PowerNode transformation. template struct TransformTree : public TransformTreeNonRecursive {}; // helper struct that does the actual transformation for a composite node. We need this additional struct // to extract the template argument list with the types of all children from the node, which we cannot do // directly in the transformation<> template, as the type passed to transformation<> will usually be a // derived type and will normally have more template arguments than just the children. This declaration // just introduces the type of the helper struct, we always instantiate the specialization defined below; template struct transform_composite_node; // specialized version of the helper struct which extracts the template argument list with the children from // its second template parameter, which has to be CompositeNode::ChildTypes. Apart from that, the struct is // similar to the one for a PowerNode, but it obviously delegates transformation of the children to the TMP. template struct transform_composite_node,T> { // transformed type, using the same nested struct trick as the PowerNode typedef ImplementationTag Tag; typedef typename LookupNodeTransformation::type NodeTransformation; typedef typename NodeTransformation::template result, LookupNodeTransformation>::type::recursive >::transformed_type... >::type transformed_type; typedef typename NodeTransformation::template result, LookupNodeTransformation>::type::recursive >::transformed_type... >::storage_type transformed_storage_type; // Retrieve the transformation descriptor for the child with index i. // This little helper improves really improves the readability of the // transformation functions. template struct ChildTransformation : public TransformTree::Type, T, NodeTag::Type>, LookupNodeTransformation< typename S::template Child::Type, T, ImplementationTag::Type> >::type::recursive > {}; template static transformed_type transform(const S& s, T& t, index_pack indices) { return NodeTransformation::transform(s,t,ChildTransformation::transform_storage(s.template childStorage(),t)...); } template static transformed_type transform(const S& s, const T& t, index_pack indices) { return NodeTransformation::transform(s,t,ChildTransformation::transform_storage(s.template childStorage(),t)...); } template static transformed_storage_type transform_storage(std::shared_ptr sp, T& t, index_pack indices) { return NodeTransformation::transform_storage(sp,t,ChildTransformation::transform_storage(sp->template childStorage(),t)...); } template static transformed_storage_type transform_storage(std::shared_ptr sp, const T& t, index_pack indices) { return NodeTransformation::transform_storage(sp,t,ChildTransformation::transform_storage(sp->template childStorage(),t)...); } }; // the specialization of transformation<> for the CompositeNode. This just extracts the // CompositeNode::ChildTypes member and forwards to the helper struct template struct TransformTree { private: typedef typename S::ChildTypes ChildTypes; static typename tuple_index_pack_builder::type child_indices() { return typename tuple_index_pack_builder::type(); } public: typedef typename transform_composite_node::transformed_type transformed_type; typedef typename transform_composite_node::transformed_storage_type transformed_storage_type; static transformed_type transform(const S& s, T& t) { return transform_composite_node::transform(s,t,child_indices()); } static transformed_type transform(const S& s, const T& t) { return transform_composite_node::transform(s,t,child_indices()); } static transformed_storage_type transform_storage(std::shared_ptr sp, T& t) { return transform_composite_node::transform_storage(sp,t,child_indices()); } static transformed_storage_type transform_storage(std::shared_ptr sp, const T& t) { return transform_composite_node::transform_storage(sp,t,child_indices()); } }; // non-recursive version of the CompositeNode transformation. template struct TransformTree : public TransformTreeNonRecursive {}; #endif // DOXYGEN //! \} group Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_TRANSFORMATION_HH dune-typetree-2.5.0/dune/typetree/transformationutilities.hh000066400000000000000000000005621302546717000244370ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_TRANSFORMATIONUTILITIES_HH #define DUNE_TYPETREE_TRANSFORMATIONUTILITIES_HH #include #include #endif // DUNE_TYPETREE_TRANSFORMATIONUTILITIES_HH dune-typetree-2.5.0/dune/typetree/traversal.hh000066400000000000000000000154001302546717000214350ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_TRAVERSAL_HH #define DUNE_TYPETREE_TRAVERSAL_HH #if HAVE_RVALUE_REFERENCES #include #endif #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup Tree Traversal * \ingroup TypeTree * \{ */ #ifndef DOXYGEN // these are all internals and not public API. Only access is using applyToTree(). // This struct is the core of the algorithm. While this specialization simply serves as the starting point // of the traversal and takes care of some setup work, the struct has to be specialized for each TreeType node type it // should support. // The first parameter specifies the kind of TreePath (dynamic/static) to use, the second one is the tag of the node type // and the third one must always be specialized as true, as a value of false means the node should in fact not be visited. // That case is already handled by a specialization of the struct. template struct ApplyToTree { template static void apply(Node&& node, Visitor&& visitor) { ApplyToTree>::apply(std::forward(node), std::forward(visitor), TreePathFactory::create(node).mutablePath()); } }; // Do not visit nodes the visitor is not interested in template struct ApplyToTree { // we won't do anything with the objects, so having them all const // works fine. template static void apply(const Node& node, const Visitor& visitor, TreePath treePath) {} }; // ******************************************************************************** // LeafNode // ******************************************************************************** // LeafNode - just call the leaf() callback template struct ApplyToTree { template static void apply(N&& n, V&& v, TreePath tp) { v.leaf(std::forward(n),tp.view()); } }; // ******************************************************************************** // PowerNode // ******************************************************************************** // Traverse PowerNode statically - in this case, we simply use the // generic child traversal algorithm template<> struct ApplyToTree : public ApplyToGenericCompositeNode { }; // Traverse PowerNode dynamically. Here, we exploit the fact that is possible // to do the child traversal using runtime iteration, as that saves a lot of // template instantiations. template<> struct ApplyToTree { template static void apply(N&& n, V&& v, TreePath tp) { // first encounter of this node v.pre(std::forward(n),tp.view()); // strip types of possible references typedef typename std::remove_reference::type Node; typedef typename std::remove_reference::type Visitor; // get child type typedef typename Node::template Child<0>::Type C; // Do we have to visit the children? As the TreePath is dynamic, it does not // contain any information that could be evaluated at compile time, so we only // have to query the visitor once. const bool visit = Visitor::template VisitChild::value; // iterate over children for (std::size_t k = 0; k < degree(n); ++k) { // always call beforeChild(), regardless of the value of visit v.beforeChild(std::forward(n),n.child(k),tp.view(),k); // update TreePath tp.push_back(k); // descend to child ApplyToTree,visit>::apply(n.child(k),std::forward(v),tp); // restore TreePath tp.pop_back(); // always call afterChild(), regardless of the value of visit v.afterChild(std::forward(n),n.child(k),tp.view(),k); // if this is not the last child, call infix callback if (k < degree(n) - 1) v.in(std::forward(n),tp.view()); } // node is done - call postfix callback v.post(std::forward(n),tp.view()); } }; // ******************************************************************************** // CompositeNode // ******************************************************************************** // Traverse CompositeNode - just forward to the generic algorithm template struct ApplyToTree : public ApplyToGenericCompositeNode { }; #endif // DOXYGEN // ******************************************************************************** // Public Interface // ******************************************************************************** //! Apply visitor to TypeTree. /** * \code #include * \endcode * This function applies the given visitor to the given tree. Both visitor and tree may be const * or non-const (if the compiler supports rvalue references, they may even be a non-const temporary). * * \note The visitor must implement the interface laid out by DefaultVisitor (most easily achieved by * inheriting from it) and specify the required type of tree traversal (static or dynamic) by * inheriting from either StaticTraversal or DynamicTraversal. * * \param tree The tree the visitor will be applied to. * \param visitor The visitor to apply to the tree. */ template void applyToTree(Tree&& tree, Visitor&& visitor) { ApplyToTree::type::treePathType>::apply(std::forward(tree), std::forward(visitor)); } //! \} group Tree Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_TRAVERSAL_HH dune-typetree-2.5.0/dune/typetree/traversalutilities.hh000066400000000000000000000056741302546717000234050ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_TRAVERSALUTILITIES_HH #define DUNE_TYPETREE_TRAVERSALUTILITIES_HH #include namespace Dune { namespace TypeTree { /** \addtogroup Tree Traversal * \ingroup TypeTree * \{ */ namespace { //! Visitor that applies a functor and an associated reduction to a TypeTree. /** * \tparam F The functor to apply to leaf nodes. Must return a ResultType. * \tparam R The reduction used to combine the results. * \tparam ResultType The result type of the operation. */ template struct LeafReductionVisitor : public TypeTree::TreeVisitor { static const TreePathType::Type treePathType = TreePathType::dynamic; template void leaf(const Node& node, TreePath treePath) { _value = _reduction(_value,_functor(node,treePath)); } LeafReductionVisitor(F functor, R reduction, ResultType startValue) : _functor(functor) , _reduction(reduction) , _value(startValue) {} ResultType result() { return _value; } F _functor; R _reduction; ResultType _value; }; } // anonymous namespace //! Calculate a quantity as a reduction over the leaf nodes of a TypeTree. /** * This function can be used to easily calculate a quantity that is a result of applying * a functor to the leaf nodes of a TypeTree and combining the functor return values. * The functor, reduction and result should all have cheap copy constructors to ensure * good performance. * * The functor must conform to the pattern * \code * struct Functor * { * template * ResultType operator()(const Node& node, TreePath treePath) const * { * return ...; * } * }; * \endcode * * \param tree The tree on which to perform the calculation. * \param functor The functor to apply to the leaf nodes. * \param reduction The operation used to combine the individual results. * \param startValue The initial value for the result. * * \returns The value obtained by combining the individual results for all leafs. */ template ResultType reduceOverLeafs(const Tree& tree, F functor, R reduction, ResultType startValue) { LeafReductionVisitor visitor(functor,reduction,startValue); TypeTree::applyToTree(tree,visitor); return visitor.result(); } //! \} group Tree Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_TRAVERSALUTILITIES_HH dune-typetree-2.5.0/dune/typetree/treepath.hh000066400000000000000000000412111302546717000212450ustar00rootroot00000000000000// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=8 sw=2 sts=2: #ifndef DUNE_TYPETREE_TREEPATH_HH #define DUNE_TYPETREE_TREEPATH_HH #include #include #include #include #include #include namespace Dune { namespace TypeTree { //! \addtogroup TreePath //! \ingroup TypeTree //! \{ namespace TreePathType { enum Type { fullyStatic, mostlyStatic, dynamic }; } template struct TreePath { constexpr TreePath() = default; constexpr TreePath(const TreePath&) = default; constexpr TreePath(TreePath&&) = default; typedef TreePath ViewType; TreePath view() { return *this; } TreePath mutablePath() { return *this; } }; template struct TreePathSize; template struct TreePathSize > : public index_constant {}; //! Returns the size (number of components) of the given `TreePath`. template constexpr std::size_t treePathSize(const TreePath&) { return sizeof...(i); } template struct TreePathPushBack; template struct TreePathPushBack,k> { typedef TreePath type; }; template struct TreePathPushFront; template struct TreePathPushFront,k> { typedef TreePath type; }; template struct TreePathBack; // There is only a single element, so return that... template struct TreePathBack > : public index_constant {}; // We need to explicitly provide two elements here, as // the template argument pack would match the empty list // and create a conflict with the single-element specialization. // Here, we just shave off the first element and recursively // instantiate ourselves. template struct TreePathBack > : public TreePathBack > {}; template struct TreePathFront; template struct TreePathFront > : public index_constant {}; template struct TreePathPopBack; template struct TreePathPopBack,i...> { typedef TreePath type; }; template struct TreePathPopBack,i...> : public TreePathPopBack,i...,j> {}; template struct TreePathPopFront; template struct TreePathPopFront > { typedef TreePath type; }; template struct TreePathConcat; template struct TreePathConcat,TreePath > { typedef TreePath type; }; template void print_tree_path(std::ostream& os) {} template void print_tree_path(std::ostream& os) { os << k << " "; print_tree_path(os); } template std::ostream& operator<<(std::ostream& os, const TreePath& tp) { os << "TreePath< "; print_tree_path(os); os << ">"; return os; } //! A TreePath that stores the path of a node as runtime information. class DynamicTreePath { public: //! Get the size (length) of this path. std::size_t size() const { return _stack.size(); } //! Get the index value at position pos. std::size_t element(std::size_t pos) const { return _stack[pos]; } //! Get the last index value. std::size_t back() const { return _stack.back(); } //! Get the first index value. std::size_t front() const { return _stack.front(); } friend std::ostream& operator<<(std::ostream& os, const DynamicTreePath& tp) { os << "TreePath( "; for (std::size_t i = 0; i < tp.size(); ++i) os << tp.element(i) << " "; os << ")"; return os; } protected: #ifndef DOXYGEN typedef FixedCapacityStackView Stack; Stack& _stack; DynamicTreePath(Stack& stack) : _stack(stack) {} #endif // DOXYGEN }; #ifndef DOXYGEN // DynamicTreePath subclasses are implementation details and never exposed to the user // This is the object that gets passed around by the traversal algorithm. It // extends the DynamicTreePath with stack-like modifier methods. Note that // it does not yet allocate any storage for the index values. It just uses // the reference to a storage vector of the base class. This implies that all // objects that are copy-constructed from each other share a single index storage! // The reason for this is to avoid differentiating the visitor signature for static // and dynamic traversal: Having very cheap copy-construction for these objects // allows us to pass them by value. class MutableDynamicTreePath : public DynamicTreePath { public: typedef DynamicTreePath ViewType; void push_back(std::size_t v) { _stack.push_back(v); } void pop_back() { _stack.pop_back(); } void set_back(std::size_t v) { _stack.back() = v; } DynamicTreePath view() { return *this; } protected: MutableDynamicTreePath(Stack& stack) : DynamicTreePath(stack) {} }; // DynamicTreePath storage provider. // This objects provides the storage for the DynamicTreePath // during the tree traversal. After construction, it should // not be used directly - the traversal framework uses the // base class returned by calling mutablePath(). template class MakeableDynamicTreePath : private FixedCapacityStack , public MutableDynamicTreePath { public: MutableDynamicTreePath mutablePath() { return static_cast(*this); } MakeableDynamicTreePath() : MutableDynamicTreePath(static_cast&>(*this)) { } }; // Factory for creating the right type of TreePath based on the requested // traversal pattern (static or dynamic). template struct TreePathFactory; // Factory for static traversal. template<> struct TreePathFactory { template static TreePath<> create(const Tree& tree) { return TreePath<>(); } }; // Factory for dynamic traversal. template<> struct TreePathFactory { template static MakeableDynamicTreePath::depth> create(const Tree& tree) { return MakeableDynamicTreePath::depth>(); } }; #endif // DOXYGEN //! A hybrid version of TreePath that supports both compile time and run time indices. /** * A `HybridTreePath` supports storing a combination of run time and compile time indices. * This makes it possible to store the tree path to a tree node inside the tree node itself, * even if the path contains one or more `PowerNode`s, where each child must have exactly the * same type. At the same time, as much information as possible is kept accessible at compile * time, allowing for more efficient algorithms. * */ template class HybridTreePath { public: //! An `index_sequence` for the entries in this `HybridTreePath`. using index_sequence = std::index_sequence_for; //! Default constructor constexpr HybridTreePath() {} constexpr HybridTreePath(const HybridTreePath& tp) = default; constexpr HybridTreePath(HybridTreePath&& tp) = default; //! Constructor from a `std::tuple` explicit constexpr HybridTreePath(std::tuple t) : _data(t) {} //! Constructor from arguments template 0 && sizeof...(U) == sizeof...(T)),bool>::type = true> explicit constexpr HybridTreePath(U... t) : _data(t...) {} //! Returns an index_sequence for enumerating the components of this HybridTreePath. constexpr static index_sequence enumerate() { return {}; } #ifndef DOXYGEN // I can't be bothered to make all the external accessors friends of HybridTreePath, // so we'll only hide the data tuple from the user in Doxygen. using Data = std::tuple; Data _data; #endif // DOXYGEN }; //! Constructs a new `HybridTreePath` from the given indices. /** * This function returns a new `HybridTreePath` with the given index values. It exists * mainly to avoid having to manually specify the exact type of the new object. */ template constexpr HybridTreePath hybridTreePath(const T&... t) { return HybridTreePath(t...); } //! Returns the size (number of components) of the given `HybridTreePath`. template constexpr std::size_t treePathSize(const HybridTreePath&) { return sizeof...(T); } //! Returns a copy of the i-th element of the `HybridTreePath`. /** * As `HybridTreePath` instances should not be mutated after their creation, this function * returns a copy of the value. As values are either `std::integral_constant` or `std::size_t`, that's * just as cheap as returning a reference. * * The index for the entry can be passed either as a template parameter or as an `index_constant`: * * \code{.cc} * auto tp = hybridTreePath(1,2,3,4); * using namespace Dune::TypeTree::Indices; * // the following two lines are equivalent * std::cout << treePathEntry<2>(tp) << std::endl; * std::cout << treePathEntry(tp,_2) << std::endl; * \endcode * */ template auto treePathEntry(const HybridTreePath& tp, index_constant = {}) -> typename std::decay(tp._data))>::type { return std::get(tp._data); } //! Returns the index value of the i-th element of the `HybridTreePath`. /** * This function always returns the actual index value, irrespective of whether the * entry is a compile time index or a run time index. * * The index for the entry can be passed either as a template parameter or as an `index_constant`: * * \code{.cc} * auto tp = hybridTreePath(1,2,3,4); * using namespace Dune::TypeTree::Indices; * // the following two lines are equivalent * std::cout << treePathIndex<2>(tp) << std::endl; * std::cout << treePathIndex(tp,_2) << std::endl; * \endcode * */ template std::size_t treePathIndex(const HybridTreePath& tp, index_constant = {}) { return std::get(tp._data); } //! Returns a copy of the last element of the `HybridTreePath`. /** * As `HybridTreePath` instances should not be mutated after their creation, this function * returns a copy of the value. As values are either `std::integral_constant` or `std::size_t`, that's * just as cheap as returning a reference. */ template 0),bool>::type = true> auto back(const HybridTreePath& tp) -> decltype(treePathEntry(tp)) { return treePathEntry(tp); } //! Returns the index value of the last element of the `HybridTreePath`. template 0),bool>::type = true> std::size_t backIndex(const HybridTreePath& tp) { return treePathEntry(tp); } //! Returns a copy of the first element of the `HybridTreePath`. /** * As `HybridTreePath` instances should not be mutated after their creation, this function * returns a copy of the value. As values are either `std::integral_constant` or `std::size_t`, that's * just as cheap as returning a reference. */ template auto front(const HybridTreePath& tp) -> decltype(treePathEntry<0>(tp)) { return treePathEntry<0>(tp); } //! Returns the index value of the first element of the `HybridTreePath`. template std::size_t frontIndex(const HybridTreePath& tp) { return treePathEntry<0>(tp); } //! Appends a run time index to a `HybridTreePath`. /** * This function returns a new `HybridTreePath` with the run time index `i` appended. */ template HybridTreePath push_back(const HybridTreePath& tp, std::size_t i) { return HybridTreePath(std::tuple_cat(tp._data,std::make_tuple(i))); } //! Appends a compile time index to a `HybridTreePath`. /** * This function returns a new `HybridTreePath` with the compile time index `i` appended. * * The value for the new entry can be passed either as a template parameter or as an `index_constant`: * * \code{.cc} * auto tp = hybridTreePath(1,2,3,4); * using namespace Dune::TypeTree::Indices; * // the following two lines are equivalent * auto tp_a = push_back<1>(tp); * auto tp_b = push_back(tp,_1); * \endcode * */ template HybridTreePath> push_back(const HybridTreePath& tp, index_constant i_ = {}) { return HybridTreePath >(std::tuple_cat(tp._data,std::make_tuple(i_))); } //! Prepends a run time index to a `HybridTreePath`. /** * This function returns a new `HybridTreePath` with the run time index `i` prepended. */ template HybridTreePath push_front(const HybridTreePath& tp, std::size_t element) { return HybridTreePath(std::tuple_cat(std::make_tuple(element),tp._data)); } //! Prepends a compile time index to a `HybridTreePath`. /** * This function returns a new `HybridTreePath` with the compile time index `i` prepended. * * The value for the new entry can be passed either as a template parameter or as an `index_constant`: * * \code{.cc} * auto tp = hybridTreePath(1,2,3,4); * using namespace Dune::TypeTree::Indices; * // the following two lines are equivalent * auto tp_a = push_front<1>(tp); * auto tp_b = push_front(tp,_1); * \endcode * */ template HybridTreePath,T...> push_front(const HybridTreePath& tp, index_constant _i = {}) { return HybridTreePath,T...>(std::tuple_cat(std::make_tuple(_i),tp._data)); } #ifndef DOXYGEN namespace impl { // end of recursion template typename std::enable_if< (i == sizeof...(T)) >::type print_hybrid_tree_path(std::ostream& os, const HybridTreePath& tp, index_constant _i) {} // print current entry and recurse template typename std::enable_if< (i < sizeof...(T)) >::type print_hybrid_tree_path(std::ostream& os, const HybridTreePath& tp, index_constant _i) { os << treePathIndex(tp,_i) << " "; print_hybrid_tree_path(os,tp,index_constant{}); } } // namespace impl #endif // DOXYGEN //! Dumps a `HybridTreePath` to a stream. template std::ostream& operator<<(std::ostream& os, const HybridTreePath& tp) { os << "HybridTreePath< "; impl::print_hybrid_tree_path(os, tp, index_constant<0>{}); os << ">"; return os; } //! \} group TypeTree } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_TREEPATH_HH dune-typetree-2.5.0/dune/typetree/typetraits.hh000066400000000000000000000134761302546717000216550ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_TYPETRAITS_HH #define DUNE_TYPETREE_TYPETRAITS_HH #include #include #include #include namespace Dune { // Provide some more C++11 TMP helpers. // These should be upstreamed to dune-common ASAP. template struct first_type; template struct first_type { typedef T0 type; }; namespace TypeTree { template struct has_node_tag { struct yes { char dummy[1]; }; struct no { char dummy[2]; }; template static yes test(NodeTag *); template static no test(...); enum { /** @brief True if class T defines a NodeTag. */ value = sizeof(test(0)) == sizeof(yes) }; }; template struct has_node_tag_value { template struct maybe { char dummy[N+1]; }; struct yes { char dummy[2]; }; struct no { char dummy[1]; }; template static maybe>::value> test(NodeTag * a); template static no test(...); enum { /** @brief True if class T defines a NodeTag of type V. */ value = sizeof(test(0)) == sizeof(yes) }; }; template struct has_implementation_tag { struct yes { char dummy[1]; }; struct no { char dummy[2]; }; template static yes test(ImplementationTag *); template static no test(...); enum { /** @brief True if class T defines an ImplementationTag. */ value = sizeof(test(0)) == sizeof(yes) }; }; template struct has_implementation_tag_value { template struct maybe { char dummy[N+1]; }; struct yes { char dummy[2]; }; struct no { char dummy[1]; }; template static maybe>::value> test(ImplementationTag * a); template static no test(...); enum { /** @brief True if class T defines an ImplementationTag of type V. */ value = sizeof(test(0)) == sizeof(yes) }; }; template struct AlwaysVoid { typedef void type; }; //! Helper function for generating a pointer to a value of type T in an unevaluated operand setting. template T* declptr(); // Support for lazy evaluation of meta functions. This is required when doing // nested tag dispatch without C++11-style typedefs (based on using syntax). // The standard struct-based meta functions cause premature evaluation in a // context that is not SFINAE-compatible. We thus have to return the meta function // without evaluating it, placing that burden on the caller. On the other hand, // the lookup will often directly the target type, so here is some helper code // to automatically do the additional evaluation if necessary. // Too bad that the new syntax is GCC 4.6+... //! Marker tag declaring a meta function. /** * Just inherit from this type to cause lazy evaluation */ struct meta_function {}; //! Helper meta function to delay evaluation of F. template struct lazy_evaluate { typedef typename F::type type; }; //! Identity function. template struct lazy_identity { typedef F type; }; //! Meta function that evaluates its argument iff it inherits from meta_function. template struct evaluate_if_meta_function { typedef typename std::conditional< std::is_base_of::value, lazy_evaluate, lazy_identity >::type::type type; }; namespace impl { // Check if type is a or is derived from one of the tree path types // Default overload for types not representing a tree path constexpr auto isTreePath(void*) -> std::false_type { return std::false_type(); } // Overload for DynamicTreePath constexpr auto isTreePath(const DynamicTreePath*) -> std::true_type { return std::true_type(); } // Overload for instances of TreePath<...> template constexpr auto isTreePath(const TreePath*) -> std::true_type { return std::true_type(); } // Overload for instances of HybridTreePath<...> template constexpr auto isTreePath(const HybridTreePath*) -> std::true_type { return std::true_type(); } } /** * \brief Check if type represents a tree path * * If T is a or derived from one of the tree path types this * struct derives from std::true_type, otherwise from std::false_type. * Hence the result of the check is available via ::value, cast to bool, * or operator(). * * \tparam T Check if this type represents a tree path */ template struct IsTreePath : public decltype(impl::isTreePath((typename std::decay::type*)(nullptr))) {}; /** * \brief Check if given object represents a tree path * * \tparam T Check if this type represents a tree path * \returns std::true_type if argument is a tree path and std::false_type if not */ template constexpr auto isTreePath(const T&) -> IsTreePath { return IsTreePath(); } } // end namespace TypeTree } // end namespace Dune #endif // DUNE_TYPETREE_TYPETRAITS_HH dune-typetree-2.5.0/dune/typetree/typetree.hh000066400000000000000000000012471302546717000212770ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_HH #define DUNE_TYPETREE_HH #include #include #include #include #include #include #include #include #include #include #include #include #endif // DUNE_TYPETREE_HH dune-typetree-2.5.0/dune/typetree/utility.hh000066400000000000000000000220761302546717000211440ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_UTILITY_HH #define DUNE_TYPETREE_UTILITY_HH #include #include #include #include #include #include #include #include namespace Dune { namespace TypeTree { /** \addtogroup TypeTree * \{ */ #ifndef DOXYGEN template std::shared_ptr convert_arg(const T& t) { return std::make_shared(t); } template std::shared_ptr convert_arg(T& t) { return stackobject_to_shared_ptr(t); } template T& assertGridViewType(T& t) { static_assert((std::is_same::value), "GridViewType must be equal in all components of composite type"); return t; } // only bind to real rvalues template typename std::enable_if::value,std::shared_ptr >::type convert_arg(T&& t) { return std::make_shared(std::forward(t)); } #endif // DOXYGEN //! Struct for obtaining some basic structural information about a TypeTree. /** * This struct extracts basic information about the passed TypeTree and * presents them in a static way suitable for use as compile-time constants. * * \tparam Tree The TypeTree to examine. * \tparam Tag Internal parameter, leave at default value. */ template struct TreeInfo { private: // Start the tree traversal typedef TreeInfo> NodeInfo; public: //! The depth of the TypeTree. static const std::size_t depth = NodeInfo::depth; //! The total number of nodes in the TypeTree. static const std::size_t nodeCount = NodeInfo::nodeCount; //! The number of leaf nodes in the TypeTree. static const std::size_t leafCount = NodeInfo::leafCount; }; #ifndef DOXYGEN // ******************************************************************************** // TreeInfo specializations for the different node types // ******************************************************************************** // leaf node template struct TreeInfo { static const std::size_t depth = 1; static const std::size_t nodeCount = 1; static const std::size_t leafCount = 1; }; // power node - exploit the fact that all children are identical template struct TreeInfo { typedef TreeInfo> ChildInfo; static const std::size_t depth = 1 + ChildInfo::depth; static const std::size_t nodeCount = 1 + StaticDegree::value * ChildInfo::nodeCount; static const std::size_t leafCount = StaticDegree::value * ChildInfo::leafCount; }; namespace { // TMP for iterating over the children of a composite node // identical for both composite node implementations template struct generic_compositenode_children_info { typedef generic_compositenode_children_info NextChild; // extract child info typedef typename Node::template Child::Type Child; typedef NodeTag ChildTag; typedef TreeInfo ChildInfo; // combine information of current child with info about following children static const std::size_t maxDepth = ChildInfo::depth > NextChild::maxDepth ? ChildInfo::depth : NextChild::maxDepth; static const std::size_t nodeCount = ChildInfo::nodeCount + NextChild::nodeCount; static const std::size_t leafCount = ChildInfo::leafCount + NextChild::leafCount; }; // End of recursion template struct generic_compositenode_children_info { static const std::size_t maxDepth = 0; static const std::size_t nodeCount = 0; static const std::size_t leafCount = 0; }; } // anonymous namespace // Struct for building information about composite node template struct GenericCompositeNodeInfo { typedef generic_compositenode_children_info::value> Children; static const std::size_t depth = 1 + Children::maxDepth; static const std::size_t nodeCount = 1 + Children::nodeCount; static const std::size_t leafCount = Children::leafCount; }; // CompositeNode: delegate to GenericCompositeNodeInfo template struct TreeInfo : public GenericCompositeNodeInfo {}; #endif // DOXYGEN //! Simple holder class for a template argument pack of indices. /** * The main use of index_pack is to unpack variadically templated * data structures like this: * * \code * template * void apply_to_tuple(const T& t, F f, index_pack indices) * { * discard((f(get(t)),0)...); * } * * std::tuple t; * apply_to_tuple(t,foo,tuple_indices(t)); * \endcode * * \sa tuple_indices() * \sa discard() */ template struct index_pack {}; //! TMP to build an index_pack containing the sequence 0,...,n-1. template struct index_pack_builder : public index_pack_builder { #ifdef DOXYGEN //! Result. typedef index_pack<0,1,...,n-1> type; #endif // DOXYGEN }; #ifndef DOXYGEN // end of recursion template struct index_pack_builder<0,i...> { typedef index_pack type; }; #endif // DOXYGEN //! TMP to build an index_pack for all elements in the tuple. template struct tuple_index_pack_builder : public index_pack_builder::value> {}; //! Generate an index_pack for the tuple t. template typename tuple_index_pack_builder::type tuple_indices(const tuple& t) { return typename tuple_index_pack_builder::type(); } //! Generate an index_pack with the values {0, 1, ..., n-1}. /** * \tparam n The length of the index pack. * \return index_pack<0,1,...,n-1>. **/ template typename index_pack_builder::type index_range(std::integral_constant = {}) { return typename index_pack_builder::type(); } using Dune::index_constant; namespace Indices = Dune::Indices; //! No-op function to make calling a function on a variadic template argument pack legal C++. /** * \sa index_pack */ template void discard(Args&&... args) {} //! Policies for the function apply_to_tuple(). namespace apply_to_tuple_policy { //! Do not pass the index of the current tuple to the functor struct no_pass_index {}; //! Pass the index of the current tuple to the functor as its first argument in a std::integral_constant. struct pass_index {}; //! Default policy. typedef no_pass_index default_policy; } namespace { // version that does not pass index template void _apply_to_tuple(T&& t, F&& f, std::index_sequence,apply_to_tuple_policy::no_pass_index) { discard((f(std::get(std::forward(t))),0)...); } // version that passes index template void _apply_to_tuple(T&& t, F&& f, std::index_sequence,apply_to_tuple_policy::pass_index) { discard((f(index_constant{},std::get(std::forward(t))),0)...); } } //! Apply a functor to each element of a std::tuple. /* * This function applies the functor f to each element of the std::tuple t. * It works for arbitrary combinations of const- and non const lvalues and rvalues. * The function accepts an optional policy argument that can currently be used to make * it pass the index of the current tuple argument to the functor as a compile time constant * in addition to the tuple element itself. */ template void apply_to_tuple(T&& t, F&& f, Policy = apply_to_tuple_policy::default_policy()) { const std::size_t size = std::tuple_size::type>::value; _apply_to_tuple( std::forward(t), std::forward(f), std::make_index_sequence{}, Policy() ); } //! \} group TypeTree } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_UTILITY_HH dune-typetree-2.5.0/dune/typetree/visitor.hh000066400000000000000000000347321302546717000211420ustar00rootroot00000000000000// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_TYPETREE_VISITOR_HH #define DUNE_TYPETREE_VISITOR_HH #include namespace Dune { namespace TypeTree { /** \addtogroup Tree Traversal * \ingroup TypeTree * \{ */ //! Visitor interface and base class for TypeTree visitors. /** * DefaultVisitor defines the interface for visitors that can be applied to a TypeTree * using applyToTree(). Each method of the visitor is passed a node of the tree (either as * a mutable or a const reference, depending on the constness of the tree applyToTree() was * called with). The second argument is of type TreePath and denotes the exact position of the * node within the TypeTree, encoded as child indices starting at the root node. * * In order to create a functioning visitor, an implementation will - in addition to providing the methods * of this class - also have to contain the following template struct, which is used to determine * whether to visit a given node: * * \code * template * struct VisitChild * { * static const bool value = ...; // decide whether to visit Child * }; * \endcode * * For the two most common scenarios - visiting only direct children and visiting the whole tree - there * are mixin classes VisitDirectChildren and VisitTree and combined base classes TreeVisitor and * DirectChildrenVisitor. The latter two inherit from both DefaultVisitor and one of the two mixin classes * and can thus be used as convenient base classes. * * \note This class can also be used as a convenient base class if the implemented visitor * only needs to act on some of the possible callback sites, avoiding a lot of boilerplate code. */ struct DefaultVisitor { //! Method for prefix tree traversal. /** * This method gets called when first encountering a non-leaf node and * before visiting any of its children. * * \param t The node to visit. * \param treePath The position of the node within the TypeTree. */ template void pre(T&& t, TreePath treePath) const {} //! Method for infix tree traversal. /** * This method gets called BETWEEN visits of children of a non-leaf node. * That definition implies that this method will only be called for nodes * with at least two children. * * \param t The node to visit. * \param treePath The position of the node within the TypeTree. */ template void in(T&& t, TreePath treePath) const {} //! Method for postfix tree traversal. /** * This method gets called after all children of a non-leaf node have * been visited. * * \param t The node to visit. * \param treePath The position of the node within the TypeTree. */ template void post(T&& t, TreePath treePath) const {} //! Method for leaf traversal. /** * This method gets called when encountering a leaf node within the TypeTree. * * \param t The node to visit. * \param treePath The position of the node within the TypeTree. */ template void leaf(T&& t, TreePath treePath) const {} //! Method for parent-child traversal. /** * This method gets called before visiting a child node. * * \note This method gets called even if the visitor decides not to visit the child in question. * * \param t The parent node. * \param child The child node that will (potentially) be visited next. * \param treePath The position of the parent node within the TypeTree. * \param childIndex The index of the child node in relation to the parent node. */ template void beforeChild(T&& t, Child&& child, TreePath treePath, ChildIndex childIndex) const {} //! Method for child-parent traversal. /** * This method gets called after visiting a child node. * * \note This method gets called even if the child node was not visited because the visitor * chose not to do so. * * \param t The parent node. * \param child The child node that was visited last (if the visitor did not reject it). * \param treePath The position of the parent node within the TypeTree. * \param childIndex The index of the child node in relation to the parent node. */ template void afterChild(T&& t, Child&& child, TreePath treePath, ChildIndex childIndex) const {} }; //! Visitor interface and base class for visitors of pairs of TypeTrees. /** * DefaultPairVisitor defines the interface for visitors that can be applied to a pair of TypeTrees * using applyToTreePair(). Each method of the visitor is passed a node of both trees (either as * a mutable or a const reference, depending on the constness of the tree applyToTreePair() was * called with). The last argument is of type TreePath and denotes the exact position of the * nodes within the TypeTrees, encoded as child indices starting at the root node. * * In order to create a functioning visitor, an implementation will - in addition to providing the methods * of this class - also have to contain the following template struct, which is used to determine * whether to visit a given node: * * \code * template * struct VisitChild * { * static const bool value = ...; // decide whether to visit Child * }; * \endcode * * For the two most common scenarios - visiting only direct children and visiting the whole tree - there * are mixin classes VisitDirectChildren and VisitTree and combined base classes TreePairVisitor and * DirectChildrenPairVisitor. The latter two inherit from both DefaultVisitor and one of the two mixin classes * and can thus be used as convenient base classes. * * \note If your compiler does not support rvalue references, both trees must be either const or * non-const. If you call applyToTreePair() with two trees of different constness, they will * both be made const. * * \note This class can also be used as a convenient base class if the implemented visitor * only needs to act on some of the possible callback sites, avoiding a lot of boilerplate code. */ struct DefaultPairVisitor { //! Method for prefix tree traversal. /** * This method gets called when first encountering a non-leaf node and * before visiting any of its children. * * \param t1 The node of the first tree to visit. * \param t2 The node of the second tree to visit. * \param treePath The position of the node within the TypeTree. */ template void pre(T1&& t1, T2&& t2, TreePath treePath) const {} //! Method for infix tree traversal. /** * This method gets called BETWEEN visits of children of a non-leaf node. * That definition implies that this method will only be called for nodes * with at least two children. * * \param t1 The node of the first tree to visit. * \param t2 The node of the second tree to visit. * \param treePath The position of the node within the TypeTree. */ template void in(T1&& t1, T2&& t2, TreePath treePath) const {} //! Method for postfix traversal. /** * This method gets called after all children of a non-leaf node have * been visited. * * \param t1 The node of the first tree to visit. * \param t2 The node of the second tree to visit. * \param treePath The position of the node within the TypeTree. */ template void post(T1&& t1, T2&& t2, TreePath treePath) const {} //! Method for leaf traversal. /** * This method gets called when encountering a leaf node within the pair of TypeTrees. * * \attention Since the two TypeTrees are not required to be exactly identical, * it is only guaranteed that at least one of the nodes is a leaf node, * not both. * * \param t1 The node of the first tree to visit. * \param t2 The node of the second tree to visit. * \param treePath The position of the node within the TypeTree. */ template void leaf(T1&& t1, T2&& t2, TreePath treePath) const {} //! Method for parent-child traversal. /** * This method gets called before visiting a child node. * * \note This method gets called even if the visitor decides not to visit the child in question. * * \param t1 The node of the first tree to visit. * \param child1 The child of t1 to visit. * \param t2 The node of the second tree to visit. * \param child2 The child of t2 to visit. * \param treePath The position of the parent nodes within the TypeTree. * \param childIndex The index of the child nodes in relation to the parent nodes. */ template void beforeChild(T1&& t1, Child1&& child1, T2&& t2, Child2&& child2, TreePath treePath, ChildIndex childIndex) const {} //! Method for child-parent traversal. /** * This method gets called after visiting a child node. * * \note This method gets called even if the visitor decides not to visit the child in question. * * \param t1 The node of the first tree to visit. * \param child1 The child of t1 to visit. * \param t2 The node of the second tree to visit. * \param child2 The child of t2 to visit. * \param treePath The position of the parent nodes within the TypeTree. * \param childIndex The index of the child nodes in relation to the parent nodes. */ template void afterChild(T1&& t1, Child1&& child1, T2&& t2, Child2&& child2, TreePath treePath, ChildIndex childIndex) const {} }; //! Mixin base class for visitors that only want to visit the direct children of a node. /** * This mixin class will reject all children presented to it, causing the algorithm to * only visit the root node and call DefaultVisitor::beforeChild() and DefaultVisitor::afterChild() * for its direct children. */ struct VisitDirectChildren { // the little trick with the default template arguments // makes the class usable for both single-tree visitors // and visitors for pairs of trees //! Template struct for determining whether or not to visit a given child. template struct VisitChild { //! Do not visit any child. static const bool value = false; }; }; //! Mixin base class for visitors that want to visit the complete tree. /** * This mixin class will accept all children presented to it and thus make the iterator * traverse the entire tree. */ struct VisitTree { // the little trick with the default template arguments // makes the class usable for both single-tree visitors // and visitors for pairs of trees //! Template struct for determining whether or not to visit a given child. template struct VisitChild { //! Visit any child. static const bool value = true; }; }; //! Mixin base class for visitors that require a static TreePath during traversal. /** * \warning Static traversal should only be used if absolutely necessary, as it tends * to increase compilation times and object sizes (especially if compiling * with debug information)! * * \sa DynamicTraversal */ struct StaticTraversal { //! Use the static tree traversal algorithm. static const TreePathType::Type treePathType = TreePathType::fullyStatic; }; //! Mixin base class for visitors that only need a dynamic TreePath during traversal. /** * \note Dynamic traversal is preferable to static traversal, as it causes fewer * template instantiations, which improves compile time and reduces object * size (especially if compiling with debug information). * * \sa StaticTraversal */ struct DynamicTraversal { //! Use the dynamic tree traversal algorithm. static const TreePathType::Type treePathType = TreePathType::dynamic; }; //! Convenience base class for visiting the entire tree. struct TreeVisitor : public DefaultVisitor , public VisitTree {}; //! Convenience base class for visiting the direct children of a node. struct DirectChildrenVisitor : public DefaultVisitor , public VisitDirectChildren {}; //! Convenience base class for visiting an entire tree pair. struct TreePairVisitor : public DefaultPairVisitor , public VisitTree {}; //! Convenience base class for visiting the direct children of a node pair. struct DirectChildrenPairVisitor : public DefaultPairVisitor , public VisitDirectChildren {}; //! \} group Tree Traversal } // namespace TypeTree } //namespace Dune #endif // DUNE_TYPETREE_VISITOR_HH dune-typetree-2.5.0/stamp-vc000066400000000000000000000000001302546717000157600ustar00rootroot00000000000000dune-typetree-2.5.0/test/000077500000000000000000000000001302546717000152745ustar00rootroot00000000000000dune-typetree-2.5.0/test/.gitignore000066400000000000000000000002741302546717000172670ustar00rootroot00000000000000testfilteredcompositenode testproxynode testtypetree testtypetree-legacy testtypetree-no-rvalue-refs testtypetree-no-sfinae testtypetree-no-variadic testtypetreetransformation *.log *.trs dune-typetree-2.5.0/test/CMakeLists.txt000066400000000000000000000013311302546717000200320ustar00rootroot00000000000000exclude_from_headercheck( typetreetargetnodes.hh typetreetestswitch.hh typetreetestutility.hh) dune_add_test(SOURCES testtypetree.cc COMPILE_DEFINITIONS TEST_TYPETREE) foreach(TEST_FAILURE 2 3 5 6) dune_add_test(NAME testtypetree_fail${TEST_FAILURE} SOURCES testtypetree.cc COMPILE_DEFINITIONS TEST_TYPETREE;FAILURE${TEST_FAILURE} EXPECT_COMPILE_FAIL) endforeach() dune_add_test(SOURCES testtypetreetransformation.cc COMPILE_DEFINITIONS TEST_TYPETREE) dune_add_test(SOURCES testfilteredcompositenode.cc COMPILE_DEFINITIONS TEST_TYPETREE) dune_add_test(SOURCES testproxynode.cc COMPILE_DEFINITIONS TEST_TYPETREE) dune-typetree-2.5.0/test/testfilteredcompositenode.cc000066400000000000000000000063751302546717000231050ustar00rootroot00000000000000#include "config.h" #include "typetreetestswitch.hh" #if TEST_TYPETREE_INVALID int main() { return 0; } #else #include #include "typetreetestutility.hh" #include "typetreetargetnodes.hh" #include struct LeafFilter : public Dune::TypeTree::SimpleFilter { template struct apply { static const bool value = std::is_same::value; }; }; template class SimpleFilteredNode : public Dune::TypeTree::FilteredCompositeNode , public Counter { typedef Dune::TypeTree::FilteredCompositeNode BaseT; public: typedef SimpleCompositeTag ImplementationTag; static const char* name() { return "SimpleFilteredNode"; } SimpleFilteredNode(Node& node) : BaseT(node) {} }; template void testFilteredCompositeNode(Node& node, Filter filter) { typedef SimpleFilteredNode FN; FN filteredNode(node); Dune::TypeTree::applyToTree(filteredNode,TreePrinter()); typedef Dune::TypeTree::TreeInfo TI; std::cout << "depth: " << TI::depth << std::endl << "nodes: " << TI::nodeCount << std::endl << "leafs: " << TI::leafCount << std::endl; typedef Dune::TypeTree::TransformTree Transformation; typedef typename Transformation::Type TFN; TFN tfn = Transformation::transform(filteredNode); typedef Dune::TypeTree::TreeInfo TTI; static_assert(TTI::depth == TI::depth, "error in transformation with filtered node"); static_assert(TTI::nodeCount == TI::nodeCount, "error in transformation with filtered node"); static_assert(TTI::leafCount == TI::leafCount, "error in transformation with filtered node"); Dune::TypeTree::applyToTree(tfn,TreePrinter()); } int main(int argc, char** argv) { SimpleLeaf sl1; typedef SimplePower SP1; SP1 sp1_1; sp1_1.setChild(0,sl1); sp1_1.setChild(1,sl1); sp1_1.setChild(2,sl1); SimpleLeaf sl2; SP1 sp1_2(sl2,false); typedef SimpleComposite SC1; SC1 sc1_1(sl1,sp1_2,sl2); typedef SimpleComposite SC2; SC2 sc2(sl1,sl1,sl1); typedef SimpleComposite SVC1; SVC1 svc1_1(sl1,sp1_1,sl2,sc1_1); SP1 sp1_3(SimpleLeaf(),SimpleLeaf(),sl1); SVC1 svc1_2(SimpleLeaf(),SP1(sp1_2),sl2,const_cast(sc1_1)); typedef SimpleComposite SVC2; SVC2 svc2_1(sl1,svc1_2,sl2,sp1_3,sc1_1); testFilteredCompositeNode(svc2_1,LeafFilter()); testFilteredCompositeNode(svc2_1,LeafFilter()); testFilteredCompositeNode(svc2_1,Dune::TypeTree::IndexFilter<1,3,2>()); testFilteredCompositeNode(svc2_1,Dune::TypeTree::IndexFilter<1,3,2>()); typedef Dune::TypeTree::IndexFilter<3,1,0,4,1,2,1,0,2,1> IndexFilter1; testFilteredCompositeNode(svc2_1,IndexFilter1()); testFilteredCompositeNode(svc2_1,IndexFilter1()); typedef SimpleFilteredNode SFN; SFN sfn(svc2_1); testFilteredCompositeNode(sfn,IndexFilter1()); testFilteredCompositeNode(sfn,IndexFilter1()); return 0; } #endif dune-typetree-2.5.0/test/testproxynode.cc000066400000000000000000000040431302546717000205330ustar00rootroot00000000000000#include "config.h" #include #include "typetreetestutility.hh" template class SimpleProxy : public Dune::TypeTree::ProxyNode { typedef Dune::TypeTree::ProxyNode BaseT; public: static const char* name() { return "SimpleProxy"; } int id() const { return this->proxiedNode().id(); } SimpleProxy(Node& node) : BaseT(node) {} }; template void testProxyNode(Node& node) { typedef SimpleProxy ProxyNode; ProxyNode proxyNode(node); Dune::TypeTree::applyToTree(proxyNode,TreePrinter()); typedef Dune::TypeTree::TreeInfo TI_Node; typedef Dune::TypeTree::TreeInfo TI_ProxyNode; static_assert(TI_Node::depth == TI_ProxyNode::depth, "Proxy node has wrong depth"); static_assert(TI_Node::nodeCount == TI_ProxyNode::nodeCount, "Proxy node has wrong node count"); static_assert(TI_Node::leafCount == TI_ProxyNode::leafCount, "Proxy node has wrong leaf count"); } int main(int argc, char** argv) { // basic tests // leaf node SimpleLeaf sl1; typedef SimplePower SP1; SP1 sp1_1; sp1_1.setChild(0,sl1); sp1_1.setChild(1,sl1); sp1_1.setChild(2,sl1); SimpleLeaf sl2; SP1 sp1_2(sl2,false); Dune::TypeTree::applyToTree(sp1_1,TreePrinter()); typedef SimpleComposite SC1; SC1 sc1_1(sl1,sp1_2,sl2); typedef SimpleComposite SC2; SC2 sc2(sl1,sl1,sl1); testProxyNode(sl1); testProxyNode(sp1_1); testProxyNode(sc1_1); testProxyNode(sl1); testProxyNode(sp1_1); testProxyNode(sc1_1); typedef SimpleComposite SVC1; SVC1 svc1_1(sl1,sp1_1,sl2,sc1_1); SP1 sp1_3(SimpleLeaf(),SimpleLeaf(),sl1); SVC1 svc1_2(SimpleLeaf(),SP1(sp1_2),sl2,const_cast(sc1_1)); typedef SimpleComposite SVC2; SVC2 svc2_1(sl1,svc1_2,sl2,sp1_3,sc1_1); testProxyNode(svc2_1); testProxyNode(svc2_1); return 0; } dune-typetree-2.5.0/test/testtypetree.cc000066400000000000000000000105151302546717000203460ustar00rootroot00000000000000#include "config.h" #include "typetreetestswitch.hh" #if TEST_TYPETREE_INVALID int main() { return 0; } #else #include "typetreetestutility.hh" struct NodeCountingFunctor { typedef std::size_t result_type; template struct doVisit { static const bool value = true; }; template struct visit { static const result_type result = 1; }; }; struct LeafCountingFunctor { typedef std::size_t result_type; template struct doVisit { static const bool value = Node::isLeaf; }; template struct visit { static const result_type result = 1; }; }; struct DepthFunctor { typedef std::size_t result_type; template struct doVisit { static const bool value = Node::isLeaf; }; template struct visit { // the TreePath is always one entry shorter than the actual depth of the tree static const result_type result = Dune::TypeTree::TreePathSize::value + 1; }; }; int main(int argc, char** argv) { // basic tests // leaf node TreePrinter treePrinter; SimpleLeaf sl1; Dune::TypeTree::applyToTree(sl1,treePrinter); typedef SimplePower SP1; SP1 sp1_1; sp1_1.setChild(0,sl1); sp1_1.setChild(1,sl1); sp1_1.setChild(2,sl1); Dune::TypeTree::applyToTree(sp1_1,TreePrinter()); SimpleLeaf sl2; SP1 sp1_2(sl2,false); Dune::TypeTree::applyToTree(sp1_2,TreePrinter()); SP1 sp1_2a(sl2,true); Dune::TypeTree::applyToTree(sp1_2a,TreePrinter()); typedef SimpleComposite SC1; SC1 sc1_1(sl1,sp1_2,sl2); Dune::TypeTree::applyToTree(const_cast(sc1_1),treePrinter); typedef SimpleComposite SC2; SC2 sc2(sl1,sl1,sl1); typedef SimpleComposite SVC1; SVC1 svc1_1(sl1,sp1_1,sl2,sc1_1); Dune::TypeTree::applyToTree(svc1_1,treePrinter); SP1 sp1_3(SimpleLeaf(),SimpleLeaf(),sl1); Dune::TypeTree::applyToTree(sp1_3,TreePrinter()); SVC1 svc1_2(SimpleLeaf(),SP1(sp1_2),sl2,const_cast(sc1_1)); Dune::TypeTree::applyToTree(svc1_2,TreePrinter()); typedef SimpleComposite SVC2; SVC2 svc2_1(sl1,sc2,sl2,sc1_1); Dune::TypeTree::applyToTreePair(svc1_2,svc2_1,PairPrinter()); typedef Dune::TypeTree::TreeInfo TI; // test TreeInfo static_assert(TI::depth == 4 && TI::nodeCount == 14 && TI::leafCount == 10, "TreeInfo yields wrong information"); std::cout << "depth: " << TI::depth << std::endl << "nodes: " << TI::nodeCount << std::endl << "leafs: " << TI::leafCount << std::endl; static_assert((Dune::TypeTree::AccumulateValue< SVC2, NodeCountingFunctor, Dune::TypeTree::plus, 0>::result == TI::nodeCount), "Error in AccumulateValue"); static_assert((Dune::TypeTree::AccumulateValue< SVC2, LeafCountingFunctor, Dune::TypeTree::plus, 0>::result == TI::leafCount), "Error in AccumulateValue"); static_assert((Dune::TypeTree::AccumulateValue< SVC2, DepthFunctor, Dune::TypeTree::max, 0>::result == TI::depth), "Error in AccumulateValue"); // Test valid and invalid child access. Invalid access should be caught at compile time auto const _0 = Dune::TypeTree::index_constant<0>(); auto const _1 = Dune::TypeTree::index_constant<1>(); auto const _2 = Dune::TypeTree::index_constant<2>(); auto const _3 = Dune::TypeTree::index_constant<3>(); // 1: valid access auto x1 = child(sp1_1, _0); #ifdef FAILURE2 // 2: invalid access (too few children) auto x2 = child(sp1_1, _3); #endif #ifdef FAILURE3 // 3: invalid access (child has no children) auto x3 = child(sp1_1, _0, _0); #endif // 4: valid access auto x4 = child(sc1_1, _1, _2); #ifdef FAILURE5 // 5: invalid access (too few children) auto x5 = child(sc1_1, _3); #endif #ifdef FAILURE6 // 6: invalid access (child has no children) auto x6 = child(sc1_1, _0, _0); #endif return 0; } #endif dune-typetree-2.5.0/test/testtypetreetransformation.cc000066400000000000000000000024701302546717000233360ustar00rootroot00000000000000#include "config.h" #include "typetreetestswitch.hh" #if TEST_TYPETREE_INVALID int main() { return 0; } #else #include "typetreetestutility.hh" #include "typetreetargetnodes.hh" int main(int argc, char** argv) { // basic tests // leaf node TreePrinter treePrinter; SimpleLeaf sl1; Dune::TypeTree::applyToTree(sl1,treePrinter); Dune::TypeTree::TransformTree::transformed_type tl1 = Dune::TypeTree::TransformTree::transform(sl1,TestTransformation()); typedef SimplePower SP1; SP1 sp1_1; sp1_1.setChild(0,sl1); sp1_1.setChild(1,sl1); sp1_1.setChild(2,sl1); SimpleLeaf sl2; SP1 sp1_2(sl2,false); typedef SimpleComposite SVC1; SVC1 svc1_1(SimpleLeafDerived(),sp1_2,sl1); Dune::TypeTree::applyToTree(sp1_1,TreePrinter()); TestTransformation trafo; Dune::TypeTree::TransformTree::transformed_type tp1_1 = Dune::TypeTree::TransformTree::transform(sp1_1,trafo); Dune::TypeTree::TransformTree::transformed_type tvc1_1 = Dune::TypeTree::TransformTree::transform(svc1_1,TestTransformation()); Dune::TypeTree::applyToTree(tvc1_1,TreePrinter()); return 0; } #endif dune-typetree-2.5.0/test/typetreetargetnodes.hh000066400000000000000000000050151302546717000217170ustar00rootroot00000000000000struct TargetLeaf : public Dune::TypeTree::LeafNode { template TargetLeaf(const SimpleLeaf& sl, const Transformation& t) : s(Dune::stackobject_to_shared_ptr(sl)) {} template TargetLeaf(Dune::shared_ptr sl, const Transformation& t) : s(sl) {} Dune::shared_ptr s; const char* name() const { return "TargetLeaf"; } int id() const { return s->id(); } }; template struct TargetPower : public Dune::TypeTree::PowerNode { template TargetPower(const S& sc, const Transformation& t, const std::array,k>& children) : Dune::TypeTree::PowerNode(children) , s(Dune::stackobject_to_shared_ptr(sc)) {} template TargetPower(Dune::shared_ptr sc, const Transformation& t, const std::array,k>& children) : Dune::TypeTree::PowerNode(children) , s(sc) {} Dune::shared_ptr s; const char* name() const { return "TargetPower"; } int id() const { return s->id(); } }; template struct TargetComposite : public Dune::TypeTree::CompositeNode { template TargetComposite(const S& sc, const Transformation& t, Dune::shared_ptr... children) : Dune::TypeTree::CompositeNode(children...) , s(Dune::stackobject_to_shared_ptr(sc)) {} template TargetComposite(Dune::shared_ptr sc, const Transformation& t, Dune::shared_ptr... children) : Dune::TypeTree::CompositeNode(children...) , s(sc) {} Dune::shared_ptr s; const char* name() const { return "TargetComposite"; } int id() const { return s->id(); } }; struct TestTransformation {}; // register leaf node template Dune::TypeTree::GenericLeafNodeTransformation registerNodeTransformation(SL* sl, TestTransformation* t, SimpleLeafTag* tag); template Dune::TypeTree::GenericPowerNodeTransformation registerNodeTransformation(SP* sp, TestTransformation* t, SimplePowerTag* tag); template Dune::TypeTree::GenericCompositeNodeTransformation registerNodeTransformation(SC* sc, TestTransformation* t, SimpleCompositeTag* tag); dune-typetree-2.5.0/test/typetreetestswitch.hh000066400000000000000000000004521302546717000216010ustar00rootroot00000000000000#ifndef DUNE_TYPETREE_TEST_TYPETREESWITCH_HH #define DUNE_TYPETREE_TEST_TYPETREESWITCH_HH #ifdef TEST_TYPETREE // nothing to do right now - no fallback code to test... #else #error You need to specify a test case via preprocessor define! #endif #endif // DUNE_TYPETREE_TEST_TYPETREESWITCH_HH dune-typetree-2.5.0/test/typetreetestutility.hh000066400000000000000000000077221302546717000220120ustar00rootroot00000000000000 #include #include #include struct Counter { Counter() : _id(_ids++) { std::cout << "Constructed id = " << id() << std::endl; } Counter(const Counter& rhs) : _id(_ids++) { rhs.assert_valid(); std::cout << "Copy-Constructed id = " << id() << " from id = " << rhs.id() << std::endl; } Counter(Counter&& rhs) : _id(rhs._id) { rhs.assert_valid(); rhs._id = -1; std::cout << "Move-Constructed id = " << id() << std::endl; } ~Counter() { std::cout << "Destructed id = " << _id << std::endl; } Counter& operator=(const Counter& rhs) { rhs.assert_valid(); assert_valid(); std::cout << "Assigned id = " << id() << " from id = " << rhs.id() << std::endl; return *this; } Counter& operator=(Counter&& rhs) { assert_valid(); rhs.assert_valid(); std::cout << "Move-Assigned id = " << id() << " from id = " << rhs.id() << std::endl; rhs._id = -1; return *this; } int id() const { assert_valid(); return _id; } void assert_valid() const { assert(_id != -1); } int _id; static int _ids; }; int Counter::_ids = 0; struct SimpleLeafTag {}; struct SimpleLeaf : public Dune::TypeTree::LeafNode , public Counter { typedef SimpleLeafTag ImplementationTag; static const char* name() { return "SimpleLeaf"; } SimpleLeaf() {} SimpleLeaf(SimpleLeaf&& rhs) : Dune::TypeTree::LeafNode(std::move(rhs)) , Counter(std::move(rhs)) { std::cout << "move ctor" << std::endl; } SimpleLeaf(const SimpleLeaf& rhs) : Dune::TypeTree::LeafNode(rhs) , Counter(rhs) { std::cout << "copy ctor" << std::endl; } }; struct SimpleLeafDerived : public SimpleLeaf { static const char* name() { return "SimpleLeafDerived"; } }; struct SimplePowerTag {}; template struct SimplePower : public Dune::TypeTree::PowerNode , public Counter { typedef SimplePowerTag ImplementationTag; static const char* name() { return "SimplePower"; } typedef Dune::TypeTree::PowerNode BaseT; SimplePower() {} SimplePower(T& c, bool copy) : BaseT(c,copy) {} template SimplePower(C1&& c1, C2&& c2, Children&&... children) : BaseT(std::forward(c1),std::forward(c2),std::forward(children)...) {} }; struct SimpleCompositeTag {}; template struct SimpleComposite : public Dune::TypeTree::CompositeNode , public Counter { typedef SimpleCompositeTag ImplementationTag; static const char* name() { return "SimpleComposite"; } typedef Dune::TypeTree::CompositeNode BaseT; template::type> SimpleComposite(Args&&... args) : BaseT(std::forward(args)...) {} }; struct TreePrinter : public Dune::TypeTree::TreeVisitor , public Dune::TypeTree::DynamicTraversal { template void leaf(const T& t, TreePath treePath) const { pre(t,treePath); } template void pre(const T& t, TreePath treePath) const { for (std::size_t i = 0; i < treePath.size(); ++i) std::cout << " "; std::cout << t.name() << " " << t.id() << std::endl; } }; struct PairPrinter : public Dune::TypeTree::TreePairVisitor , public Dune::TypeTree::DynamicTraversal { template void leaf(const T1& t1, const T2& t2, TreePath treePath) const { pre(t1,t2,treePath); } template void pre(const T1& t1, const T2& t2, TreePath treePath) const { for (std::size_t i = 0; i < treePath.size(); ++i) std::cout << " "; std::cout << t1.name() << " " << t1.id() << " " << t2.name() << " " << t2.id() << std::endl; } };