Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
61a8ad5c
Commit
61a8ad5c
authored
May 11, 2016
by
Matthias Vallentin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove maybe<T> vestiges
parent
2d32e8b4
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
6 additions
and
700 deletions
+6
-700
libcaf_core/caf/detail/invoke_result_visitor.hpp
libcaf_core/caf/detail/invoke_result_visitor.hpp
+1
-1
libcaf_core/caf/error.hpp
libcaf_core/caf/error.hpp
+4
-4
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+0
-1
libcaf_core/caf/maybe.hpp
libcaf_core/caf/maybe.hpp
+0
-693
libcaf_core/caf/none.hpp
libcaf_core/caf/none.hpp
+1
-1
No files found.
libcaf_core/caf/detail/invoke_result_visitor.hpp
View file @
61a8ad5c
...
...
@@ -64,7 +64,7 @@ public:
(
*
this
)(
empty_msg
);
}
// unwrap
maybe
s
// unwrap
optional
s
template
<
class
T
>
void
operator
()(
optional
<
T
>&
x
)
{
if
(
x
)
...
...
libcaf_core/caf/error.hpp
View file @
61a8ad5c
...
...
@@ -40,10 +40,10 @@ namespace caf {
/// # Design goals
///
/// The error type in CAF is meant to allow efficient packing of errors
///
in either `maybe` or on the wire. For this purpose, CAF limits the
///
error code to 255 to allow storing the context size along the code
/// in
a 32-bit integer (1 bit invaldity flag, 23 bit context size, 8 bit code;
///
if the validity flag is 1,
then the error is invalid and has no category).
///
on the wire. For this purpose, CAF limits the error code to 255 to allow
///
storing the context size along the code in a 32-bit integer (1 bit
/// in
valdity flag, 23 bit context size, 8 bit code; if the validity flag is 1,
/// then the error is invalid and has no category).
///
/// # Why not `std::error_code` or `std::error_condition`?
///
...
...
libcaf_core/caf/fwd.hpp
View file @
61a8ad5c
...
...
@@ -27,7 +27,6 @@ namespace caf {
// -- 1 param templates --------------------------------------------------------
template
<
class
>
class
maybe
;
template
<
class
>
class
optional
;
template
<
class
>
class
intrusive_ptr
;
template
<
class
>
class
weak_intrusive_ptr
;
...
...
libcaf_core/caf/maybe.hpp
deleted
100644 → 0
View file @
2d32e8b4
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_MAYBE_HPP
#define CAF_MAYBE_HPP
#include <new>
#include <utility>
#include "caf/none.hpp"
#include "caf/unit.hpp"
#include "caf/error.hpp"
#include "caf/config.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/detail/safe_equal.hpp"
namespace
caf
{
/// Represents a computation returning either `T` or `std::error_condition`.
/// Note that the error condition might be default-constructed. In this case,
/// a `maybe` represents simply `none`. Hence, this type has three possible
/// states:
/// - A value of `T` is available
/// + `valid()` returns `true`
/// + `empty()` returns `false`
/// + `invalid()` returns `false`
/// - No value is available but no error occurred
/// + `valid()` returns `false`
/// + `empty()` returns `true`
/// + `invalid()` returns `false`
/// - An error occurred (no value available)
/// + `valid()` returns `false`
/// + `empty()` returns `false`
/// + `invalid()` returns `true`
template
<
class
T
>
class
maybe
{
public:
using
type
=
typename
std
::
remove_reference
<
T
>::
type
;
using
reference
=
type
&
;
using
const_reference
=
const
type
&
;
using
pointer
=
type
*
;
using
const_pointer
=
const
type
*
;
using
error_type
=
caf
::
error
;
/// Type for storing values.
using
storage
=
typename
std
::
conditional
<
std
::
is_reference
<
T
>::
value
,
std
::
reference_wrapper
<
type
>
,
T
>::
type
;
/// Creates an instance representing an error.
maybe
(
const
error_type
&
x
)
{
cr_error
(
x
);
}
/// Creates an instance representing an error.
maybe
(
error_type
&&
x
)
{
cr_error
(
std
::
move
(
x
));
}
/// Creates an instance representing a value from `x`.
template
<
class
U
,
class
=
typename
std
::
enable_if
<
std
::
is_convertible
<
U
,
T
>
::
value
>::
type
>
maybe
(
U
&&
x
)
{
cr_value
(
std
::
forward
<
U
>
(
x
));
}
template
<
class
U0
,
class
U1
,
class
...
Us
>
maybe
(
U0
&&
x0
,
U1
&&
x1
,
Us
&&
...
xs
)
{
flag_
=
available_flag
;
new
(
&
value_
)
storage
(
std
::
forward
<
U0
>
(
x0
),
std
::
forward
<
U1
>
(
x1
),
std
::
forward
<
Us
>
(
xs
)...);
}
/// Creates an instance representing an error
/// from a type offering the free function `make_error`.
template
<
class
E
,
class
=
typename
std
::
enable_if
<
std
::
is_same
<
decltype
(
make_error
(
std
::
declval
<
const
E
&
>())),
error
>::
value
>::
type
>
maybe
(
E
error_enum
)
:
maybe
(
make_error
(
error_enum
))
{
// nop
}
/// Creates an empty instance.
maybe
()
:
flag_
(
empty_flag
)
{
// nop
}
/// Creates an empty instance.
maybe
(
const
none_t
&
)
:
flag_
(
empty_flag
)
{
// nop
}
maybe
(
const
maybe
&
other
)
{
if
(
other
.
valid
())
cr_value
(
other
.
value_
);
else
cr_error
(
other
);
}
maybe
(
maybe
&&
other
)
{
if
(
other
.
valid
())
cr_value
(
std
::
move
(
other
.
value_
));
else
cr_error
(
std
::
move
(
other
));
}
template
<
class
U
>
maybe
(
maybe
<
U
>&&
other
)
{
static_assert
(
std
::
is_convertible
<
U
,
T
>::
value
,
"U not convertible to T"
);
if
(
other
)
cr_value
(
std
::
move
(
*
other
));
else
cr_error
(
std
::
move
(
other
.
error
()));
}
template
<
class
U
>
maybe
(
const
maybe
<
U
>&
other
)
{
static_assert
(
std
::
is_convertible
<
U
,
T
>::
value
,
"U not convertible to T"
);
if
(
other
)
cr_value
(
*
other
);
else
cr_error
(
other
.
error
());
}
~
maybe
()
{
destroy
();
}
maybe
&
operator
=
(
const
none_t
&
)
{
if
(
!
empty
())
{
destroy
();
flag_
=
empty_flag
;
}
return
*
this
;
}
template
<
class
U
,
class
=
typename
std
::
enable_if
<
std
::
is_convertible
<
U
,
T
>
::
value
>::
type
>
maybe
&
operator
=
(
U
&&
x
)
{
if
(
!
valid
())
{
destroy
();
cr_value
(
std
::
forward
<
U
>
(
x
));
}
else
{
assign_value
(
std
::
forward
<
U
>
(
x
));
}
return
*
this
;
}
maybe
&
operator
=
(
const
error_type
&
err
)
{
destroy
();
cr_error
(
err
);
return
*
this
;
}
maybe
&
operator
=
(
error_type
&&
err
)
{
destroy
();
cr_error
(
std
::
move
(
err
));
return
*
this
;
}
template
<
class
E
,
class
=
typename
std
::
enable_if
<
std
::
is_same
<
decltype
(
make_error
(
std
::
declval
<
const
E
&
>())),
error_type
>::
value
>::
type
>
maybe
&
operator
=
(
E
error_enum
)
{
return
*
this
=
make_error
(
error_enum
);
}
maybe
&
operator
=
(
maybe
&&
other
)
{
if
(
other
.
valid
())
*
this
=
std
::
move
(
*
other
);
else
cr_error
(
std
::
move
(
other
));
return
*
this
;
}
maybe
&
operator
=
(
const
maybe
&
other
)
{
if
(
other
.
valid
())
*
this
=
*
other
;
else
cr_error
(
other
);
return
*
this
;
}
template
<
class
U
>
maybe
&
operator
=
(
maybe
<
U
>&&
other
)
{
static_assert
(
std
::
is_convertible
<
U
,
T
>::
value
,
"U not convertible to T"
);
if
(
other
.
valid
())
*
this
=
std
::
move
(
*
other
);
else
cr_error
(
std
::
move
(
other
));
return
*
this
;
}
template
<
class
U
>
maybe
&
operator
=
(
const
maybe
<
U
>&
other
)
{
static_assert
(
std
::
is_convertible
<
U
,
T
>::
value
,
"U not convertible to T"
);
if
(
other
.
valid
())
*
this
=
*
other
;
else
cr_error
(
other
);
return
*
this
;
}
/// Queries whether this instance holds a value.
bool
valid
()
const
{
return
flag_
==
available_flag
;
}
/// Returns `available()`.
explicit
operator
bool
()
const
{
return
valid
();
}
/// Returns `! available()`.
bool
operator
!
()
const
{
return
!
valid
();
}
/// Returns the value.
reference
get
()
{
CAF_ASSERT
(
valid
());
return
value_
;
}
/// Returns the value.
const_reference
get
()
const
{
CAF_ASSERT
(
valid
());
return
value_
;
}
/// Returns the value.
reference
operator
*
()
{
return
get
();
}
/// Returns the value.
const_reference
operator
*
()
const
{
return
get
();
}
/// Returns a pointer to the value.
pointer
operator
->
()
{
return
&
get
();
}
/// Returns a pointer to the value.
const_pointer
operator
->
()
const
{
return
&
get
();
}
/// Returns whether this objects holds neither a value nor an actual error.
bool
empty
()
const
{
return
flag_
==
empty_flag
;
}
bool
invalid
()
const
{
return
(
flag_
&
error_code_mask
)
!=
0
;
}
/// Creates an error object.
error_type
error
()
const
{
if
(
valid
())
return
{};
if
(
has_error_context
())
return
{
error_code
(),
extended_error_
->
first
,
make_message
(
extended_error_
->
second
)};
return
{
error_code
(),
error_category_
};
}
uint8_t
error_code
()
const
{
return
static_cast
<
uint8_t
>
(
flag_
&
error_code_mask
);
}
atom_value
error_category
()
const
{
if
(
valid
())
return
atom
(
""
);
if
(
has_error_context
())
return
extended_error_
->
first
;
return
error_category_
;
}
private:
bool
has_error_context
()
const
{
return
(
flag_
&
error_context_mask
)
!=
0
;
}
void
destroy
()
{
if
(
valid
())
value_
.
~
storage
();
else
if
(
has_error_context
())
delete
extended_error_
;
}
template
<
class
V
>
void
assign_value
(
V
&&
x
)
{
using
x_type
=
typename
std
::
remove_reference
<
V
>::
type
;
using
fwd_type
=
typename
std
::
conditional
<
std
::
is_rvalue_reference
<
decltype
(
x
)
>::
value
&&
!
std
::
is_reference
<
T
>::
value
,
x_type
&&
,
x_type
&
>::
type
;
value_
=
static_cast
<
fwd_type
>
(
x
);
}
template
<
class
V
>
void
cr_value
(
V
&&
x
)
{
using
x_type
=
typename
std
::
remove_reference
<
V
>::
type
;
using
fwd_type
=
typename
std
::
conditional
<
std
::
is_rvalue_reference
<
decltype
(
x
)
>::
value
&&
!
std
::
is_reference
<
T
>::
value
,
x_type
&&
,
x_type
&
>::
type
;
flag_
=
available_flag
;
new
(
&
value_
)
storage
(
static_cast
<
fwd_type
>
(
x
));
}
template
<
class
U
>
void
cr_error
(
const
maybe
<
U
>&
other
)
{
flag_
=
other
.
flag_
;
if
(
has_error_context
())
extended_error_
=
new
extended_error
(
*
other
.
extended_error_
);
else
error_category_
=
other
.
error_category_
;
}
template
<
class
U
>
void
cr_error
(
maybe
<
U
>&&
other
)
{
flag_
=
other
.
flag_
;
if
(
has_error_context
())
extended_error_
=
other
.
extended_error_
;
else
error_category_
=
other
.
error_category_
;
other
.
flag_
=
empty_flag
;
// take ownership of extended_error_
}
void
cr_error
(
const
error_type
&
x
)
{
flag_
=
x
.
compress_code_and_size
();
if
(
has_error_context
())
extended_error_
=
new
extended_error
(
x
.
category
(),
to_string
(
x
.
context
()));
else
error_category_
=
x
.
category
();
}
void
cr_error
(
error_type
&&
x
)
{
flag_
=
x
.
compress_code_and_size
();
if
(
has_error_context
())
extended_error_
=
new
extended_error
(
x
.
category
(),
to_string
(
x
.
context
()));
else
error_category_
=
x
.
category
();
}
static
constexpr
uint32_t
available_flag
=
0x80000000
;
static
constexpr
uint32_t
empty_flag
=
0x00000000
;
static
constexpr
uint32_t
error_code_mask
=
0x000000FF
;
static
constexpr
uint32_t
error_context_mask
=
0x7FFFFF00
;
using
extended_error
=
std
::
pair
<
atom_value
,
std
::
string
>
;
// stores the availability flag (1bit), context string size (23 bit),
// and error code (8 bit).
uint32_t
flag_
;
union
{
// if flag == available_flag
storage
value_
;
// if (flag & error_context_mask) == 0
atom_value
error_category_
;
// if (flag & error_context_mask) != 0
extended_error
*
extended_error_
;
};
};
// Represents a computation performing side effects only and
// maybely return a `std::error_condition`.
template
<
>
class
maybe
<
void
>
{
public:
using
type
=
unit_t
;
using
reference
=
const
type
&
;
using
const_reference
=
const
type
&
;
using
pointer
=
const
type
*
;
using
const_pointer
=
const
type
*
;
using
error_type
=
caf
::
error
;
maybe
()
=
default
;
maybe
(
const
unit_t
&
)
{
// nop
}
maybe
(
const
none_t
&
)
{
// nop
}
maybe
(
error_type
err
)
:
error_
(
std
::
move
(
err
))
{
// nop
}
template
<
class
E
,
class
=
typename
std
::
enable_if
<
std
::
is_same
<
decltype
(
make_error
(
std
::
declval
<
const
E
&
>())),
error_type
>::
value
>::
type
>
maybe
(
E
error_code
)
:
error_
(
make_error
(
error_code
))
{
// nop
}
maybe
&
operator
=
(
const
none_t
&
)
{
error_
.
clear
();
return
*
this
;
}
maybe
&
operator
=
(
error_type
err
)
{
error_
=
std
::
move
(
err
);
return
*
this
;
}
template
<
class
E
,
class
=
typename
std
::
enable_if
<
std
::
is_same
<
decltype
(
make_error
(
std
::
declval
<
const
E
&
>())),
error_type
>::
value
>::
type
>
maybe
&
operator
=
(
E
error_code
)
{
return
*
this
=
make_error
(
error_code
);
}
bool
valid
()
const
{
return
false
;
}
explicit
operator
bool
()
const
{
return
valid
();
}
bool
operator
!
()
const
{
return
!
valid
();
}
reference
get
()
{
CAF_ASSERT
(
!
"should never be called"
);
return
unit
;
}
const_reference
get
()
const
{
CAF_ASSERT
(
!
"should never be called"
);
return
unit
;
}
reference
operator
*
()
{
return
get
();
}
const_reference
operator
*
()
const
{
return
get
();
}
pointer
operator
->
()
{
return
&
get
();
}
const_pointer
operator
->
()
const
{
return
&
get
();
}
bool
empty
()
const
{
return
!
error
();
}
const
error_type
&
error
()
const
{
return
error_
;
}
private:
error_type
error_
;
};
/// Allows element-wise access of STL-compatible tuples.
/// @relates maybe
template
<
size_t
X
,
class
T
>
maybe
<
typename
std
::
tuple_element
<
X
,
T
>::
type
&>
get
(
maybe
<
T
>&
xs
)
{
if
(
xs
)
return
std
::
get
<
X
>
(
*
xs
);
return
xs
.
error
();
}
/// Allows element-wise access of STL-compatible tuples.
/// @relates maybe
template
<
size_t
X
,
class
T
>
maybe
<
const
typename
std
::
tuple_element
<
X
,
T
>::
type
&>
get
(
const
maybe
<
T
>&
xs
)
{
if
(
xs
)
return
std
::
get
<
X
>
(
*
xs
);
return
xs
.
error
();
}
/// Returns `true` if both objects represent either the same
/// value or the same error, `false` otherwise.
/// @relates maybe
template
<
class
T
,
typename
U
>
bool
operator
==
(
const
maybe
<
T
>&
x
,
const
maybe
<
U
>&
y
)
{
if
(
x
)
return
(
y
)
?
detail
::
safe_equal
(
*
x
,
*
y
)
:
false
;
if
(
x
.
empty
()
&&
y
.
empty
())
return
true
;
if
(
!
y
)
return
x
.
error_code
()
==
y
.
error_code
()
&&
x
.
error_category
()
==
y
.
error_category
();
return
false
;
}
/// Returns `true` if `lhs` is available and its value is equal to `rhs`.
template
<
class
T
,
typename
U
>
bool
operator
==
(
const
maybe
<
T
>&
x
,
const
U
&
y
)
{
return
(
x
)
?
*
x
==
y
:
false
;
}
/// Returns `true` if `rhs` is available and its value is equal to `lhs`.
/// @relates maybe
template
<
class
T
,
typename
U
>
bool
operator
==
(
const
T
&
x
,
const
maybe
<
U
>&
y
)
{
return
y
==
x
;
}
/// Returns `true` if the objects represent different
/// values or errors, `false` otherwise.
/// @relates maybe
template
<
class
T
,
typename
U
>
bool
operator
!=
(
const
maybe
<
T
>&
x
,
const
maybe
<
U
>&
y
)
{
return
!
(
x
==
y
);
}
/// Returns `true` if `lhs` is not available or its value is not equal to `rhs`.
/// @relates maybe
template
<
class
T
,
typename
U
>
bool
operator
!=
(
const
maybe
<
T
>&
x
,
const
U
&
y
)
{
return
!
(
x
==
y
);
}
/// Returns `true` if `rhs` is not available or its value is not equal to `lhs`.
/// @relates maybe
template
<
class
T
,
typename
U
>
bool
operator
!=
(
const
T
&
x
,
const
maybe
<
U
>&
y
)
{
return
!
(
x
==
y
);
}
/// Returns `! val.available() && val.error() == err`.
/// @relates maybe
template
<
class
T
>
bool
operator
==
(
const
maybe
<
T
>&
x
,
const
error
&
y
)
{
return
x
.
invalid
()
&&
y
.
compare
(
x
.
error_code
(),
x
.
error_category
())
==
0
;
}
/// Returns `! val.available() && val.error() == err`.
/// @relates maybe
template
<
class
T
>
bool
operator
==
(
const
error
&
x
,
const
maybe
<
T
>&
y
)
{
return
y
==
x
;
}
/// Returns `val.available() || val.error() != err`.
/// @relates maybe
template
<
class
T
>
bool
operator
!=
(
const
maybe
<
T
>&
x
,
const
error
&
y
)
{
return
!
(
x
==
y
);
}
/// Returns `val.available() || val.error() != err`.
/// @relates maybe
template
<
class
T
>
bool
operator
!=
(
const
error
&
x
,
const
maybe
<
T
>&
y
)
{
return
!
(
y
==
x
);
}
/// Returns `val.empty()`.
/// @relates maybe
template
<
class
T
>
bool
operator
==
(
const
maybe
<
T
>&
x
,
const
none_t
&
)
{
return
x
.
empty
();
}
/// Returns `val.empty()`.
/// @relates maybe
template
<
class
T
>
bool
operator
==
(
const
none_t
&
,
const
maybe
<
T
>&
x
)
{
return
x
.
empty
();
}
/// Returns `! val.empty()`.
/// @relates maybe
template
<
class
T
>
bool
operator
!=
(
const
maybe
<
T
>&
x
,
const
none_t
&
)
{
return
!
x
.
empty
();
}
/// Returns `! val.empty()`.
/// @relates maybe
template
<
class
T
>
bool
operator
!=
(
const
none_t
&
,
const
maybe
<
T
>&
x
)
{
return
!
x
.
empty
();
}
/// @relates maybe
template
<
class
Processor
,
class
T
>
typename
std
::
enable_if
<
Processor
::
is_saving
::
value
>::
type
serialize
(
Processor
&
sink
,
maybe
<
T
>&
x
,
const
unsigned
int
)
{
uint8_t
flag
=
x
.
empty
()
?
0
:
(
x
.
valid
()
?
1
:
2
);
sink
&
flag
;
if
(
x
.
valid
())
sink
&
*
x
;
if
(
x
.
invalid
())
{
auto
err
=
x
.
error
();
sink
&
err
;
}
}
/// @relates maybe
template
<
class
Processor
,
class
T
>
typename
std
::
enable_if
<
Processor
::
is_loading
::
value
>::
type
serialize
(
Processor
&
source
,
maybe
<
T
>&
x
,
const
unsigned
int
)
{
uint8_t
flag
;
source
&
flag
;
switch
(
flag
)
{
case
1
:
{
T
value
;
source
&
value
;
x
=
std
::
move
(
value
);
break
;
}
case
2
:
{
error
err
;
source
&
err
;
x
=
std
::
move
(
err
);
break
;
}
default:
x
=
none
;
}
}
/// @relates maybe
template
<
class
T
>
std
::
string
to_string
(
const
maybe
<
T
>&
x
)
{
if
(
x
)
return
deep_to_string
(
*
x
);
if
(
x
.
empty
())
return
"<none>"
;
return
to_string
(
x
.
error
());
}
}
// namespace caf
#endif // CAF_MAYBE_HPP
libcaf_core/caf/none.hpp
View file @
61a8ad5c
...
...
@@ -26,7 +26,7 @@
namespace
caf
{
/// Represents "nothing", e.g., for clearing a
`maybe
` by assigning `none`.
/// Represents "nothing", e.g., for clearing a
n `optional
` by assigning `none`.
struct
none_t
:
detail
::
comparable
<
none_t
>
{
constexpr
none_t
()
{
// nop
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment