Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F77963741
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
Sat, Aug 17, 12:44
Size
9 KB
Mime Type
text/x-c
Expires
Mon, Aug 19, 12:44 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
19957467
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 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 General Public License
* along with GNU Emacs; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef UTILITIES_H
#define UTILITIES_H
#include <boost/tuple/tuple.hpp>
#include <tuple>
#ifdef NO_EXPERIMENTAL
# if defined(__INTEL_COMPILER)
//# pragma warning ( disable : 383 )
# elif defined (__clang__)
// test clang to be sure that when we test for gnu it is only gnu
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Weffc++"
# elif (defined(__GNUC__) || defined(__GNUG__))
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Weffc++"
# endif
# include <boost/optional.hpp>
# if defined(__INTEL_COMPILER)
//# pragma warning ( disable : 383 )
# elif defined (__clang__)
// test clang to be sure that when we test for gnu it is only gnu
# pragma clang diagnostic pop
# pragma clang diagnostic ignored "-Weffc++"
# elif (defined(__GNUC__) || defined(__GNUG__))
# pragma GCC diagnostic pop
# pragma GCC diagnostic ignored "-Weffc++"
# endif
#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
{
template
<
size_t
size
,
typename
T
,
typename
...
tail
>
struct
tuple_array_helper
{
using
type
=
typename
tuple_array_helper
<
size
-
1
,
T
,
T
,
tail
...
>::
type
;
};
template
<
typename
T
,
typename
...
tail
>
struct
tuple_array_helper
<
0
,
T
,
tail
...
>
{
using
type
=
std
::
tuple
<
tail
...
>
;
};
template
<
typename
T
,
size_t
size
>
struct
tuple_array_provider
{
class
type
:
public
tuple_array_helper
<
size
,
T
>::
type
{
public
:
using
Parent
=
typename
tuple_array_helper
<
size
,
T
>::
type
;
inline
type
(
Parent
&&
parent
)
:
Parent
{
parent
}{};
// T operator[](size_t index) {
// return reinterpret_cast<T*>(this)[index];
// }
// T operator[](size_t index) const {
// return reinterpret_cast<T*>(this)[index];
// }
};
};
}
// 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
/* ---------------------------------------------------------------------- */
/**
* conversion helper from `boost::tuple` to `std::tuple`
*/
template
<
typename
BoostTuple
,
std
::
size_t
...
Is
>
auto
asStdTuple
(
BoostTuple
&&
boostTuple
,
std
::
index_sequence
<
Is
...
>
)
{
return
std
::
tuple
<
typename
boost
::
tuples
::
element
<
Is
,
std
::
decay_t
<
BoostTuple
>>::
type
...
>
(
boost
::
get
<
Is
>
(
std
::
forward
<
BoostTuple
>
(
boostTuple
))...);
}
/**
* conversion from `boost::tuple` to `std::tuple`
*/
template
<
typename
BoostTuple
>
auto
asStdTuple
(
BoostTuple
&&
boostTuple
)
{
return
asStdTuple
(
std
::
forward
<
BoostTuple
>
(
boostTuple
),
std
::
make_index_sequence
<
boost
::
tuples
::
length
<
std
::
decay_t
<
BoostTuple
>>::
value
>
());
}
}
// muSpectre
#endif
/* UTILITIES_H */
Event Timeline
Log In to Comment