Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F64788633
utilities.hh
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, May 29, 11:33
Size
10 KB
Mime Type
text/x-c
Expires
Fri, May 31, 11:33 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
17925128
Attached To
rMUSPECTRE µSpectre
utilities.hh
View Options
/**
* @file utilities.hh
*
* @author Till Junge <till.junge@epfl.ch>
*
* @date 17 Nov 2017
*
* @brief additions to the standard name space to anticipate C++17 features
*
* Copyright © 2017 Till Junge
*
* µSpectre is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3, or (at
* your option) any later version.
*
* µSpectre 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 Lesser General Public License
* along with µSpectre; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* * Boston, MA 02111-1307, USA.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining it
* with proprietary FFT implementations or numerical libraries, containing parts
* covered by the terms of those libraries' licenses, the licensors of this
* Program grant you additional permission to convey the resulting work.
*/
#ifndef SRC_COMMON_UTILITIES_HH_
#define SRC_COMMON_UTILITIES_HH_
#include <tuple>
#ifdef NO_EXPERIMENTAL
#include <boost/optional.hpp>
#else
#include <experimental/optional>
#endif
namespace
std_replacement
{
namespace
detail
{
template
<
class
T
>
struct
is_reference_wrapper
:
std
::
false_type
{};
template
<
class
U
>
struct
is_reference_wrapper
<
std
::
reference_wrapper
<
U
>>
:
std
::
true_type
{};
//! from cppreference
template
<
class
Base
,
class
T
,
class
Derived
,
class
...
Args
>
auto
INVOKE
(
T
Base
::*
pmf
,
Derived
&&
ref
,
Args
&&
...
args
)
noexcept
(
noexcept
(
(
std
::
forward
<
Derived
>
(
ref
).
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...)))
->
std
::
enable_if_t
<
std
::
is_function
<
T
>::
value
&&
std
::
is_base_of
<
Base
,
std
::
decay_t
<
Derived
>>::
value
,
decltype
((
std
::
forward
<
Derived
>
(
ref
).
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...))
>
{
return
(
std
::
forward
<
Derived
>
(
ref
).
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...);
}
//! from cppreference
template
<
class
Base
,
class
T
,
class
RefWrap
,
class
...
Args
>
auto
INVOKE
(
T
Base
::*
pmf
,
RefWrap
&&
ref
,
Args
&&
...
args
)
noexcept
(
noexcept
((
ref
.
get
().
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...)))
->
std
::
enable_if_t
<
std
::
is_function
<
T
>::
value
&&
is_reference_wrapper
<
std
::
decay_t
<
RefWrap
>>::
value
,
decltype
((
ref
.
get
().
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...))
>
{
return
(
ref
.
get
().
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...);
}
//! from cppreference
template
<
class
Base
,
class
T
,
class
Pointer
,
class
...
Args
>
auto
INVOKE
(
T
Base
::*
pmf
,
Pointer
&&
ptr
,
Args
&&
...
args
)
noexcept
(
noexcept
(
((
*
std
::
forward
<
Pointer
>
(
ptr
)).
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...)))
->
std
::
enable_if_t
<
std
::
is_function
<
T
>::
value
&&
!
is_reference_wrapper
<
std
::
decay_t
<
Pointer
>>::
value
&&
!
std
::
is_base_of
<
Base
,
std
::
decay_t
<
Pointer
>>::
value
,
decltype
(((
*
std
::
forward
<
Pointer
>
(
ptr
)).
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...))
>
{
return
((
*
std
::
forward
<
Pointer
>
(
ptr
)).
*
pmf
)(
std
::
forward
<
Args
>
(
args
)...);
}
//! from cppreference
template
<
class
Base
,
class
T
,
class
Derived
>
auto
INVOKE
(
T
Base
::*
pmd
,
Derived
&&
ref
)
noexcept
(
noexcept
(
std
::
forward
<
Derived
>
(
ref
).
*
pmd
))
->
std
::
enable_if_t
<
!
std
::
is_function
<
T
>::
value
&&
std
::
is_base_of
<
Base
,
std
::
decay_t
<
Derived
>>::
value
,
decltype
(
std
::
forward
<
Derived
>
(
ref
).
*
pmd
)
>
{
return
std
::
forward
<
Derived
>
(
ref
).
*
pmd
;
}
//! from cppreference
template
<
class
Base
,
class
T
,
class
RefWrap
>
auto
INVOKE
(
T
Base
::*
pmd
,
RefWrap
&&
ref
)
noexcept
(
noexcept
(
ref
.
get
().
*
pmd
))
->
std
::
enable_if_t
<
!
std
::
is_function
<
T
>::
value
&&
is_reference_wrapper
<
std
::
decay_t
<
RefWrap
>>::
value
,
decltype
(
ref
.
get
().
*
pmd
)
>
{
return
ref
.
get
().
*
pmd
;
}
//! from cppreference
template
<
class
Base
,
class
T
,
class
Pointer
>
auto
INVOKE
(
T
Base
::*
pmd
,
Pointer
&&
ptr
)
noexcept
(
noexcept
((
*
std
::
forward
<
Pointer
>
(
ptr
)).
*
pmd
))
->
std
::
enable_if_t
<
!
std
::
is_function
<
T
>::
value
&&
!
is_reference_wrapper
<
std
::
decay_t
<
Pointer
>>::
value
&&
!
std
::
is_base_of
<
Base
,
std
::
decay_t
<
Pointer
>>::
value
,
decltype
((
*
std
::
forward
<
Pointer
>
(
ptr
)).
*
pmd
)
>
{
return
(
*
std
::
forward
<
Pointer
>
(
ptr
)).
*
pmd
;
}
//! from cppreference
template
<
class
F
,
class
...
Args
>
auto
INVOKE
(
F
&&
f
,
Args
&&
...
args
)
noexcept
(
noexcept
(
std
::
forward
<
F
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...)))
->
std
::
enable_if_t
<
!
std
::
is_member_pointer
<
std
::
decay_t
<
F
>>::
value
,
decltype
(
std
::
forward
<
F
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...))
>
{
return
std
::
forward
<
F
>
(
f
)(
std
::
forward
<
Args
>
(
args
)...);
}
}
// namespace detail
//! from cppreference
template
<
class
F
,
class
...
ArgTypes
>
auto
invoke
(
F
&&
f
,
ArgTypes
&&
...
args
)
// exception specification for QoI
noexcept
(
noexcept
(
detail
::
INVOKE
(
std
::
forward
<
F
>
(
f
),
std
::
forward
<
ArgTypes
>
(
args
)...)))
->
decltype
(
detail
::
INVOKE
(
std
::
forward
<
F
>
(
f
),
std
::
forward
<
ArgTypes
>
(
args
)...))
{
return
detail
::
INVOKE
(
std
::
forward
<
F
>
(
f
),
std
::
forward
<
ArgTypes
>
(
args
)...);
}
namespace
detail
{
//! from cppreference
template
<
class
F
,
class
Tuple
,
std
::
size_t
...
I
>
constexpr
decltype
(
auto
)
apply_impl
(
F
&&
f
,
Tuple
&&
t
,
std
::
index_sequence
<
I
...
>
)
{
return
std_replacement
::
invoke
(
std
::
forward
<
F
>
(
f
),
std
::
get
<
I
>
(
std
::
forward
<
Tuple
>
(
t
))...);
}
}
// namespace detail
//! from cppreference
template
<
class
F
,
class
Tuple
>
constexpr
decltype
(
auto
)
apply
(
F
&&
f
,
Tuple
&&
t
)
{
return
detail
::
apply_impl
(
std
::
forward
<
F
>
(
f
),
std
::
forward
<
Tuple
>
(
t
),
std
::
make_index_sequence
<
std
::
tuple_size
<
std
::
decay_t
<
Tuple
>>::
value
>
{});
}
}
// namespace std_replacement
namespace
muSpectre
{
namespace
internal
{
/**
* helper struct template to compute the type of a tuple with a
* given number of entries of the same type
*/
template
<
size_t
size
,
typename
T
,
typename
...
tail
>
struct
tuple_array_helper
{
//! underlying tuple
using
type
=
typename
tuple_array_helper
<
size
-
1
,
T
,
T
,
tail
...
>::
type
;
};
/**
* helper struct template to compute the type of a tuple with a
* given number of entries of the same type
*/
template
<
typename
T
,
typename
...
tail
>
struct
tuple_array_helper
<
0
,
T
,
tail
...
>
{
//! underlying tuple
using
type
=
std
::
tuple
<
tail
...
>
;
};
/**
* helper struct for runtime index access to
* tuples. RecursionLevel indicates how much more we can recurse
* down
*/
template
<
class
TupArr
,
size_t
Index
=
0
,
size_t
RecursionLevel
=
TupArr
::
Size
-
1
>
struct
Accessor
{
using
Stored_t
=
typename
TupArr
::
Stored_t
;
inline
static
Stored_t
get
(
const
size_t
&
index
,
TupArr
&
container
)
{
if
(
index
==
Index
)
{
return
std
::
get
<
Index
>
(
container
);
}
else
{
return
Accessor
<
TupArr
,
Index
+
1
,
RecursionLevel
-
1
>::
get
(
index
,
container
);
}
}
inline
static
const
Stored_t
get
(
const
size_t
&
index
,
const
TupArr
&
container
)
{
if
(
index
==
Index
)
{
return
std
::
get
<
Index
>
(
container
);
}
else
{
return
Accessor
<
TupArr
,
Index
+
1
,
RecursionLevel
-
1
>::
get
(
index
,
container
);
}
}
};
/**
* specialisation for recursion end
*/
template
<
class
TupArr
,
size_t
Index
>
struct
Accessor
<
TupArr
,
Index
,
0
>
{
using
Stored_t
=
typename
TupArr
::
Stored_t
;
inline
static
Stored_t
get
(
const
size_t
&
index
,
TupArr
&
container
)
{
if
(
index
==
Index
)
{
return
std
::
get
<
Index
>
(
container
);
}
else
{
std
::
stringstream
err
{};
err
<<
"Index "
<<
index
<<
"is out of range."
;
throw
std
::
runtime_error
(
err
.
str
());
}
}
inline
static
const
Stored_t
get
(
const
size_t
&
index
,
const
TupArr
&
container
)
{
if
(
index
==
Index
)
{
return
std
::
get
<
Index
>
(
container
);
}
else
{
std
::
stringstream
err
{};
err
<<
"Index "
<<
index
<<
"is out of range."
;
throw
std
::
runtime_error
(
err
.
str
());
}
}
};
/**
* helper struct that provides the tuple_array.
*/
template
<
typename
T
,
size_t
size
>
struct
tuple_array_provider
{
//! tuple type that can be used (almost) like an `std::array`
class
type
:
public
tuple_array_helper
<
size
,
T
>::
type
{
public
:
//! short-hand
using
Parent
=
typename
tuple_array_helper
<
size
,
T
>::
type
;
using
Stored_t
=
T
;
constexpr
static
size_t
Size
{
size
};
//! constructor
explicit
inline
type
(
Parent
&&
parent
)
:
Parent
{
parent
}
{}
//! element access
T
operator
[](
const
size_t
&
index
)
{
return
Accessor
<
type
>::
get
(
index
,
*
this
);
}
//! element access
const
T
operator
[](
const
size_t
&
index
)
const
{
return
Accessor
<
type
>::
get
(
index
,
*
this
);
}
protected
:
};
};
}
// namespace internal
/**
* This is a convenience structure to create a tuple of `nb_elem`
* entries of type `T`. It is named tuple_array, because it is
* somewhat similar to an `std::array<T, nb_elem>`. The reason for
* this structure is that the `std::array` is not allowed by the
* standard to store references (8.3.2 References, paragraph 5:
* "There shall be no references to references, no arrays of
* references, and no pointers to references.") use this, if you
* want to have a statically known number of references to store,
* and you wish to do so efficiently.
*/
template
<
typename
T
,
size_t
nb_elem
>
using
tuple_array
=
typename
internal
::
tuple_array_provider
<
T
,
nb_elem
>::
type
;
using
std_replacement
::
apply
;
/**
* emulation `std::optional` (a C++17 feature)
*/
template
<
class
T
>
#ifdef NO_EXPERIMENTAL
using
optional
=
typename
boost
::
optional
<
T
>
;
#else
using
optional
=
typename
std
::
experimental
::
optional
<
T
>
;
#endif
}
// namespace muSpectre
#endif
// SRC_COMMON_UTILITIES_HH_
Event Timeline
Log In to Comment