Bertini 2 - C++ Core
Software for Numerical Algebraic Geometry
Loading...
Searching...
No Matches
enable_permuted_arguments.hpp
Go to the documentation of this file.
1//This file is part of Bertini 2.
2//
3//enable_permuted_arguments.hpp is free software: you can redistribute it and/or modify
4//it under the terms of the GNU General Public License as published by
5//the Free Software Foundation, either version 3 of the License, or
6//(at your option) any later version.
7//
8//enable_permuted_arguments.hpp is distributed in the hope that it will be useful,
9//but WITHOUT ANY WARRANTY; without even the implied warranty of
10//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11//GNU General Public License for more details.
12//
13//You should have received a copy of the GNU General Public License
14//along with enable_permuted_arguments.hpp. If not, see <http://www.gnu.org/licenses/>.
15//
16// Copyright(C) 2015 - 2021 by Bertini2 Development Team
17//
18// See <http://www.gnu.org/licenses/> for a copy of the license,
19// as well as COPYING. Bertini2 is provided with permitted
20// additional terms in the b2/licenses/ directory.
21
22// individual authors of this file include:
23// silviana amethyst, university of wisconsin eau claire
24// additionally, this file contains code
25// based on and refined from SO post
26// https://stackoverflow.com/questions/19329297/constructor-permutations-for-passing-parameters-in-arbitrary-order
27// by user Daniel Frey.
28
36
37#ifndef BERTINI_ENABLE_PERMUTED_ARGUMENTS
38#define BERTINI_ENABLE_PERMUTED_ARGUMENTS
39
40#include <type_traits>
41#include <tuple>
42
43
44namespace bertini {
45
46
47 namespace detail {
48 // find the index of a type in a list of types,
49 // return sizeof...(Remaining) if T is not found
50 template< typename T, typename... Remaining >
51 struct IndexByType : std::integral_constant< std::size_t, 0 >
52 {};
53
54 // template specialization, enforcing the equality of the number of variadic arguments, and the corresponding index.
55 // if two types are the same, this template will be preferred since it's a closer match, and the static_assert will fail, preventing compilation.
56 template< typename T, typename... RemainingT >
57 struct IndexByType< T, T, RemainingT... > : std::integral_constant< std::size_t, 0 >
58 {
59 static_assert( IndexByType< T, RemainingT... >::value == sizeof...( RemainingT ), "No duplicates are allowed when enabling permuted arguments" );
60 };
61
62 // template specialization on two types. looks for the index of T in the latter arguments. If T1==T2, this template will not be used, but instead the above will.
63 template< typename T1, typename T2, typename... RemainingT >
64 struct IndexByType< T1, T2, RemainingT... > : std::integral_constant< std::size_t, IndexByType< T1, RemainingT... >::value + 1 >
65 {};
66
67 // a free function which gets a type from a tuple with no duplicates. Remember, duplicates are not allowed.
68 template< std::size_t I, std::size_t J,
69 typename T, typename... PresentT, typename... GivenT >
70 auto GetByIndex( const std::tuple< PresentT... >&,
71 const std::tuple< GivenT... >& absent_args )
72 -> typename std::enable_if< I == sizeof...( PresentT ), const T& >::type
73 {
74 return std::get< J >( absent_args );
75 }
76
77 // the other half of the get by index function
78 template< std::size_t I, std::size_t J,
79 typename T, typename... PresentT, typename... GivenT >
80 auto GetByIndex(const std::tuple< PresentT... >& present_args,
81 const std::tuple< GivenT... >& ) // these arguments will have to be default constructed
82 -> typename std::enable_if< I != sizeof...( PresentT ), const T& >::type /* remember, `I != sizeof...( PresentT )` means it found T in PresentT */
83 {
84 return std::get< I >( present_args );
85 }
86
87
88
89
90 // helper to validate that all Us are in Ts...
91 template< bool > struct AreValidArguments;
92
93 // the false one is never instantiated, so the 'false' template parameter will fail, deliberately
94 template<> struct AreValidArguments< true > : std::true_type
95 {};
96
97 // a proxy function which to ensure that the types are distinct, and that we can indeed get the index by type.
98 template< std::size_t... >
99 void ValidateTypes()
100 {}
101
102
103
104 // default construct the objects not present in the arguments, but required by the unpermute function
105 template< typename T >
106 struct DefaultConstruct
107 { static const T value; };
108
109 template< typename T >
110 const T DefaultConstruct< T >::value
111 {};
112
113
114
115 } // namespace detail
116
117 // helper template which reorders parameters
118 template< typename... UnpermutedT, // these must be declared when using the function
119 typename... PermutedPresentT > // these are inferred, cannot be declared
120 std::tuple< const UnpermutedT&... > Unpermute( const PermutedPresentT&... present_permuted_args )
121 {
122 using namespace detail;
123 auto present_args = std::tie( present_permuted_args... );
124 auto absent_args = std::tie( DefaultConstruct< UnpermutedT >::value... );
125
126 //next we validate that the input arguments are valid for unpermuting. must have all distinct types.
127 ValidateTypes< AreValidArguments< IndexByType< const PermutedPresentT&,
128 const UnpermutedT&... >::value != sizeof...( UnpermutedT )
129 >::value...
130 >(); // this will fail if AreValidArguments are not valid ('true')
131
132 // finally, we return a tie of the unpermuted types, default constructed if necessary
133 return std::tie( GetByIndex< IndexByType< const UnpermutedT&, const PermutedPresentT&... >::value,
134 IndexByType< const UnpermutedT&, const UnpermutedT&... >::value, UnpermutedT >
135 ( present_args, absent_args )... );
136 }
137
138
139} // re: namespace bertini
140
141#endif
std::shared_ptr< Node > I()
Definition special_number.cpp:42