Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F87236816
auto_argument.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
Fri, Oct 11, 11:14
Size
5 KB
Mime Type
text/x-c++
Expires
Sun, Oct 13, 11:14 (2 d)
Engine
blob
Format
Raw Data
Handle
21560354
Attached To
rLIBMULTISCALE LibMultiScale
auto_argument.hh
View Options
#ifndef __AUTO_ARGUMENT_HH__
#define __AUTO_ARGUMENT_HH__
/*****************************************************************/
#include <any>
#include <cxxabi.h>
#include <memory>
#include <sstream>
#include <typeinfo>
/*****************************************************************/
namespace
AutoDispatch
{
struct
Argument
{
Argument
()
=
default
;
virtual
~
Argument
()
=
default
;
template
<
typename
T
>
T
&
cast
()
{
return
dynamic_cast
<
T
&>
(
*
this
);
}
virtual
void
printself
(
std
::
ostream
&
os
)
const
{
os
<<
"("
<<
this
<<
")"
<<
Argument
::
demangle
(
typeid
(
*
this
).
name
());
};
static
std
::
string
demangle
(
const
char
*
name
)
{
int
status
=
-
4
;
// some arbitrary value to eliminate the compiler warning
std
::
unique_ptr
<
char
,
void
(
*
)(
void
*
)
>
res
{
abi
::
__cxa_demangle
(
name
,
NULL
,
NULL
,
&
status
),
std
::
free
};
auto
demangled_name
=
res
.
get
();
return
(
status
==
0
)
?
demangled_name
:
name
;
}
};
/*****************************************************************/
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
Argument
&
a
)
{
a
.
printself
(
os
);
return
os
;
}
/*****************************************************************/
struct
bad_argument_cast
:
public
std
::
exception
{
const
char
*
what
()
const
throw
()
override
{
return
str
.
c_str
();
};
std
::
string
str
;
};
template
<
typename
...
Ts
>
struct
bad_argument_cast_tmpl
:
public
bad_argument_cast
{
bad_argument_cast_tmpl
(
Argument
&
obj
)
:
real_type
(
typeid
(
obj
))
{
std
::
stringstream
sstr
;
sstr
<<
"cannot cast '"
<<
Argument
::
demangle
(
real_type
.
name
())
<<
"' into any of: ("
<<
(
Argument
::
demangle
(
typeid
(
Ts
).
name
())
+
", "
+
...)
<<
" ...)"
;
str
=
sstr
.
str
();
}
const
std
::
type_info
&
real_type
;
};
/*****************************************************************/
class
no_argument
:
public
std
::
exception
{
const
char
*
what
()
const
throw
()
override
{
return
"ArgumentAny has no value"
;
};
};
/*****************************************************************/
class
ArgumentAny
{
public
:
ArgumentAny
()
:
ptr
(
nullptr
),
s_ptr
(
nullptr
)
{}
ArgumentAny
(
const
ArgumentAny
&
other
)
:
ptr
(
other
.
ptr
),
s_ptr
(
other
.
s_ptr
),
obj
(
other
.
obj
){};
template
<
typename
T
>
constexpr
static
bool
is_Argument
=
std
::
is_base_of_v
<
Argument
,
std
::
decay_t
<
T
>>
;
template
<
typename
T
>
constexpr
static
bool
is_ArgumentAny
=
std
::
is_base_of_v
<
ArgumentAny
,
std
::
decay_t
<
T
>>
;
template
<
typename
T
,
typename
Ret
>
using
if_Argument
=
std
::
enable_if_t
<
is_Argument
<
T
>
,
Ret
>
;
template
<
typename
T
,
typename
Ret
>
using
if_not_Argument
=
std
::
enable_if_t
<
not
(
is_Argument
<
T
>
or
is_ArgumentAny
<
T
>
),
Ret
>
;
ArgumentAny
&
operator
=
(
ArgumentAny
&
val
)
{
this
->
ptr
=
val
.
ptr
;
this
->
s_ptr
=
val
.
s_ptr
;
this
->
obj
=
val
.
obj
;
return
*
this
;
}
ArgumentAny
&
operator
=
(
ArgumentAny
&&
val
)
{
obj
=
std
::
move
(
val
.
obj
);
ptr
=
val
.
ptr
;
s_ptr
=
val
.
s_ptr
;
return
*
this
;
}
template
<
typename
T
>
if_Argument
<
T
,
ArgumentAny
&>
operator
=
(
std
::
shared_ptr
<
T
>
&
val
)
{
s_ptr
=
val
;
ptr
=
nullptr
;
obj
.
reset
();
return
*
this
;
}
template
<
typename
T
>
if_Argument
<
T
,
ArgumentAny
&>
operator
=
(
T
&
val
)
{
s_ptr
.
reset
();
ptr
=
&
val
;
obj
.
reset
();
return
*
this
;
}
template
<
typename
T
>
if_Argument
<
T
,
ArgumentAny
&>
&
operator
=
(
T
&&
val
)
{
s_ptr
=
std
::
make_shared
<
T
>
(
std
::
forward
<
T
>
(
val
));
ptr
=
nullptr
;
obj
.
reset
();
return
*
this
;
}
template
<
typename
T
>
if_not_Argument
<
T
,
ArgumentAny
&>
&
operator
=
(
T
&&
val
)
{
obj
=
std
::
forward
<
T
>
(
val
);
ptr
=
nullptr
;
s_ptr
.
reset
();
return
*
this
;
}
template
<
typename
T
=
Argument
>
if_Argument
<
T
,
T
&>
get
()
{
if
(
ptr
)
return
ptr
->
cast
<
T
>
();
else
if
(
s_ptr
)
return
s_ptr
.
get
()
->
cast
<
T
>
();
throw
no_argument
();
}
template
<
typename
T
=
Argument
>
if_Argument
<
T
,
const
T
&>
get
()
const
{
if
(
ptr
)
return
ptr
->
cast
<
T
>
();
else
if
(
s_ptr
)
return
s_ptr
.
get
()
->
cast
<
T
>
();
throw
no_argument
();
}
template
<
typename
T
>
if_not_Argument
<
T
,
T
>
get
()
{
return
std
::
any_cast
<
T
>
(
obj
);
}
bool
has_value
()
const
{
return
this
->
ptr
!=
nullptr
||
s_ptr
!=
nullptr
||
obj
.
has_value
();
}
void
reset
()
{
if
(
ptr
)
ptr
=
nullptr
;
if
(
s_ptr
)
return
s_ptr
.
reset
();
obj
.
reset
();
}
private
:
Argument
*
ptr
;
std
::
shared_ptr
<
Argument
>
s_ptr
;
std
::
any
obj
;
};
/*****************************************************************/
template
<
typename
...
possible_types
>
struct
argument
{
argument
()
=
default
;
template
<
typename
T
>
argument
(
T
&&
a
)
{
arg
=
a
;
}
template
<
typename
T
>
argument
&
operator
=
(
T
&&
a
)
{
arg
=
std
::
forward
<
T
>
(
a
);
return
*
this
;
}
template
<
typename
F
>
void
visit
(
F
&&
func
)
{
bool
casted
=
false
;
casted
=
(
this
->
cast_and_call
<
possible_types
>
(
func
)
|
...);
if
(
not
casted
)
throw
bad_argument_cast_tmpl
<
possible_types
...
>
(
arg
.
get
());
}
bool
has_value
()
{
return
arg
.
has_value
();
}
private
:
template
<
typename
T
,
typename
F
>
bool
cast_and_call
(
F
&&
func
)
{
try
{
func
(
arg
.
get
<
T
>
());
return
true
;
}
catch
(
std
::
bad_cast
&
e
)
{
return
false
;
}
return
false
;
}
ArgumentAny
arg
;
};
template
<
typename
...
possible_types
>
struct
argument
<
std
::
tuple
<
possible_types
...
>>
:
public
argument
<
possible_types
...
>
{
using
argument
<
possible_types
...
>::
operator
=
;
};
/*****************************************************************/
}
// namespace AutoDispatch
#endif
//__AUTO_ARGUMENT_HH__
Event Timeline
Log In to Comment