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
052387e7
Commit
052387e7
authored
May 26, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Generalize variant API to a sum type API
parent
dd215eda
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
576 additions
and
25 deletions
+576
-25
libcaf_core/caf/default_sum_type_access.hpp
libcaf_core/caf/default_sum_type_access.hpp
+69
-0
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+26
-0
libcaf_core/caf/sum_type.hpp
libcaf_core/caf/sum_type.hpp
+172
-0
libcaf_core/caf/sum_type_access.hpp
libcaf_core/caf/sum_type_access.hpp
+40
-0
libcaf_core/caf/variant.hpp
libcaf_core/caf/variant.hpp
+1
-25
libcaf_core/test/sum_type.cpp
libcaf_core/test/sum_type.cpp
+268
-0
No files found.
libcaf_core/caf/default_sum_type_access.hpp
0 → 100644
View file @
052387e7
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* 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. *
******************************************************************************/
#pragma once
#include <cstddef>
#include <type_traits>
#include <utility>
#include "caf/detail/type_list.hpp"
namespace
caf
{
/// Allows specializing the `sum_type_access` trait for any type that simply
/// wraps a `variant` and exposes it with a `data()` member function.
template
<
class
T
>
struct
default_sum_type_access
{
using
types
=
typename
T
::
types
;
using
type0
=
typename
detail
::
tl_head
<
types
>::
type
;
static
constexpr
bool
specialized
=
true
;
template
<
int
Pos
>
static
bool
is
(
const
T
&
x
,
std
::
integral_constant
<
int
,
Pos
>
token
)
{
return
x
.
data
().
is
(
token
);
}
template
<
int
Pos
>
static
typename
detail
::
tl_at
<
types
,
Pos
>::
type
&
get
(
T
&
x
,
std
::
integral_constant
<
int
,
Pos
>
token
)
{
return
x
.
data
().
get
(
token
);
}
template
<
int
Pos
>
static
const
typename
detail
::
tl_at
<
types
,
Pos
>::
type
&
get
(
const
T
&
x
,
std
::
integral_constant
<
int
,
Pos
>
token
)
{
return
x
.
data
().
get
(
token
);
}
template
<
class
Result
,
class
Visitor
,
class
...
Ts
>
static
Result
apply
(
T
&
x
,
Visitor
&&
visitor
,
Ts
&&
...
xs
)
{
return
x
.
data
().
template
apply
<
Result
>(
std
::
forward
<
Visitor
>
(
visitor
),
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
Result
,
class
Visitor
,
class
...
Ts
>
static
Result
apply
(
const
T
&
x
,
Visitor
&&
visitor
,
Ts
&&
...
xs
)
{
return
x
.
data
().
template
apply
<
Result
>(
std
::
forward
<
Visitor
>
(
visitor
),
std
::
forward
<
Ts
>
(
xs
)...);
}
};
}
// namespace caf
libcaf_core/caf/detail/type_traits.hpp
View file @
052387e7
...
...
@@ -681,6 +681,32 @@ struct is_expected : std::false_type {};
template
<
class
T
>
struct
is_expected
<
expected
<
T
>>
:
std
::
true_type
{};
// Checks whether `T` and `U` are integers of the same size and signedness.
template
<
class
T
,
class
U
,
bool
Enable
=
std
::
is_integral
<
T
>
::
value
&&
std
::
is_integral
<
U
>::
value
&&
!
std
::
is_same
<
T
,
bool
>::
value
>
struct
is_equal_int_type
{
static
constexpr
bool
value
=
sizeof
(
T
)
==
sizeof
(
U
)
&&
std
::
is_signed
<
T
>::
value
==
std
::
is_signed
<
U
>::
value
;
};
template
<
class
T
,
typename
U
>
struct
is_equal_int_type
<
T
,
U
,
false
>
:
std
::
false_type
{
};
/// Compares `T` to `U` und evaluates to `true_type` if either
/// `T == U or if T and U are both integral types of the
/// same size and signedness. This works around the issue that
/// `uint8_t != unsigned char on some compilers.
template
<
class
T
,
typename
U
>
struct
is_same_ish
:
std
::
conditional
<
std
::
is_same
<
T
,
U
>::
value
,
std
::
true_type
,
is_equal_int_type
<
T
,
U
>
>::
type
{
};
}
// namespace detail
}
// namespace caf
libcaf_core/caf/sum_type.hpp
0 → 100644
View file @
052387e7
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* 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. *
******************************************************************************/
#pragma once
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/sum_type_access.hpp"
namespace
caf
{
/// Concept for checking whether `T` supports the sum type API by specializing
/// `sum_type_access`.
template
<
class
T
>
constexpr
bool
SumType
()
{
return
has_sum_type_access
<
typename
std
::
decay
<
T
>::
type
>::
value
;
}
/// Concept for checking whether all `Ts` support the sum type API by
/// specializing `sum_type_access`.
template
<
class
...
Ts
>
constexpr
bool
SumTypes
()
{
using
namespace
detail
;
using
types
=
type_list
<
decay_t
<
Ts
>
...
>
;
return
tl_forall
<
types
,
has_sum_type_access
>::
value
;
}
/// Returns a reference to the value of a sum type.
/// @pre `holds_alternative<T>(x)`
/// @relates SumType
template
<
class
T
,
class
U
>
detail
::
enable_if_t
<
SumType
<
U
>
(),
T
&>
get
(
U
&
x
)
{
using
namespace
detail
;
using
trait
=
sum_type_access
<
U
>
;
int_token
<
tl_index_where
<
typename
trait
::
types
,
tbind
<
is_same_ish
,
T
>::
template
type
>
::
value
>
token
;
// Silence compiler error about "binding to unrelated types" such as
// 'signed char' to 'char' (which is obvious bullshit).
return
reinterpret_cast
<
T
&>
(
trait
::
get
(
x
,
token
));
}
/// Returns a reference to the value of a sum type.
/// @pre `holds_alternative<T>(x)`
/// @relates SumType
template
<
class
T
,
class
U
>
detail
::
enable_if_t
<
SumType
<
U
>
(),
const
T
&>
get
(
const
U
&
x
)
{
using
namespace
detail
;
using
trait
=
sum_type_access
<
U
>
;
int_token
<
tl_index_where
<
typename
trait
::
types
,
tbind
<
is_same_ish
,
T
>::
template
type
>
::
x
>
token
;
// Silence compiler error about "binding to unrelated types" such as
// 'signed char' to 'char' (which is obvious bullshit).
return
reinterpret_cast
<
const
T
&>
(
trait
::
get
(
x
,
token
));
}
/// Returns a pointer to the value of a sum type if it is of type `T`,
/// `nullptr` otherwise.
/// @relates SumType
template
<
class
T
,
class
U
>
detail
::
enable_if_t
<
SumType
<
U
>
(),
T
*>
get_if
(
U
*
x
)
{
using
namespace
detail
;
using
trait
=
sum_type_access
<
U
>
;
int_token
<
tl_index_where
<
typename
trait
::
types
,
tbind
<
is_same_ish
,
T
>::
template
type
>
::
value
>
token
;
return
trait
::
is
(
*
x
,
token
)
?
&
trait
::
get
(
*
x
,
token
)
:
nullptr
;
}
/// Returns a pointer to the value of a sum type if it is of type `T`,
/// `nullptr` otherwise.
/// @relates SumType
template
<
class
T
,
class
U
>
detail
::
enable_if_t
<
SumType
<
U
>
(),
const
T
*>
get_if
(
const
U
*
x
)
{
using
namespace
detail
;
using
trait
=
sum_type_access
<
U
>
;
using
token_type
=
int_token
<
tl_index_where
<
typename
trait
::
types
,
tbind
<
is_same_ish
,
T
>::
template
type
>
::
value
>
;
token_type
token
;
static_assert
(
token_type
::
x
!=
-
1
,
"T is not part of the sum type"
);
return
trait
::
is
(
*
x
,
token
)
?
&
trait
::
get
(
*
x
,
token
)
:
nullptr
;
}
/// Returns whether a sum type has a value of type `T`.
/// @relates SumType
template
<
class
T
,
class
U
>
bool
holds_alternative
(
const
U
&
x
)
{
using
namespace
detail
;
using
trait
=
sum_type_access
<
U
>
;
int_token
<
tl_index_where
<
typename
trait
::
types
,
tbind
<
is_same_ish
,
T
>::
template
type
>
::
value
>
token
;
return
trait
::
is
(
x
,
token
);
}
template
<
bool
Valid
,
class
F
,
class
...
Ts
>
struct
sum_type_visit_result_impl
{
using
type
=
decltype
((
std
::
declval
<
F
&>
())(
std
::
declval
<
typename
sum_type_access
<
Ts
>::
type0
&>
()...));
};
template
<
class
F
,
class
...
Ts
>
struct
sum_type_visit_result_impl
<
false
,
F
,
Ts
...
>
{};
template
<
class
F
,
class
...
Ts
>
struct
sum_type_visit_result
:
sum_type_visit_result_impl
<
detail
::
conjunction
<
SumType
<
Ts
>
()...
>::
value
,
F
,
Ts
...
>
{};
template
<
class
F
,
class
...
Ts
>
using
sum_type_visit_result_t
=
typename
sum_type_visit_result
<
detail
::
decay_t
<
F
>
,
detail
::
decay_t
<
Ts
>
...
>::
type
;
template
<
class
Result
,
int
I
,
class
Visitor
>
struct
visit_impl_continuation
;
template
<
class
Result
,
int
I
>
struct
visit_impl
{
template
<
class
Visitor
,
class
T
,
class
...
Ts
>
static
Result
apply
(
Visitor
&&
f
,
T
&&
x
,
Ts
&&
...
xs
)
{
visit_impl_continuation
<
Result
,
I
-
1
,
Visitor
>
continuation
{
f
};
using
trait
=
sum_type_access
<
detail
::
decay_t
<
T
>>
;
return
trait
::
template
apply
<
Result
>(
x
,
continuation
,
std
::
forward
<
Ts
>
(
xs
)...);
}
};
template
<
class
Result
>
struct
visit_impl
<
Result
,
0
>
{
template
<
class
Visitor
,
class
...
Ts
>
static
Result
apply
(
Visitor
&&
f
,
Ts
&&
...
xs
)
{
return
f
(
std
::
forward
<
Ts
>
(
xs
)...);
}
};
template
<
class
Result
,
int
I
,
class
Visitor
>
struct
visit_impl_continuation
{
Visitor
&
f
;
template
<
class
...
Ts
>
Result
operator
()(
Ts
&&
...
xs
)
{
return
visit_impl
<
Result
,
I
>::
apply
(
f
,
std
::
forward
<
Ts
>
(
xs
)...);
}
};
/// Applies the values of any number of sum types to the visitor.
/// @relates SumType
template
<
class
Visitor
,
class
T
,
class
...
Ts
,
class
Result
=
sum_type_visit_result_t
<
Visitor
,
T
,
Ts
...>
>
detail
::
enable_if_t
<
SumTypes
<
T
,
Ts
...
>
(),
Result
>
visit
(
Visitor
&&
f
,
T
&&
x
,
Ts
&&
...
xs
)
{
return
visit_impl
<
Result
,
sizeof
...(
Ts
)
+
1
>::
apply
(
std
::
forward
<
Visitor
>
(
f
),
std
::
forward
<
T
>
(
x
),
std
::
forward
<
Ts
>
(
xs
)...);
}
}
// namespace caf
libcaf_core/caf/sum_type_access.hpp
0 → 100644
View file @
052387e7
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* 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. *
******************************************************************************/
#pragma once
#include <type_traits>
namespace
caf
{
/// Specializing this trait allows users to enable `holds_alternative`, `get`,
/// `get_if`, and `visit` for any user-defined sum type.
/// @relates SumType
template
<
class
T
>
struct
sum_type_access
{
static
constexpr
bool
specialized
=
false
;
};
/// Evaluates to `true` if `T` specializes `sum_type_access`
/// @relates SumType
template
<
class
T
>
struct
has_sum_type_access
{
static
constexpr
bool
value
=
sum_type_access
<
T
>::
specialized
;
};
}
// namespace caf
libcaf_core/caf/variant.hpp
View file @
052387e7
...
...
@@ -120,31 +120,6 @@ using variant_visit_result_t =
typename
variant_visit_result
<
detail
::
decay_t
<
F
>
,
detail
::
decay_t
<
Ts
>
...
>::
type
;
template
<
class
T
,
class
U
,
bool
Enable
=
std
::
is_integral
<
T
>
::
value
&&
std
::
is_integral
<
U
>::
value
&&
!
std
::
is_same
<
T
,
bool
>::
value
>
struct
is_equal_int_type
{
static
constexpr
bool
value
=
sizeof
(
T
)
==
sizeof
(
U
)
&&
std
::
is_signed
<
T
>::
value
==
std
::
is_signed
<
U
>::
value
;
};
template
<
class
T
,
typename
U
>
struct
is_equal_int_type
<
T
,
U
,
false
>
:
std
::
false_type
{
};
/// Compares `T` to `U` und evaluates to `true_type` if either
/// `T == U or if T and U are both integral types of the
/// same size and signedness. This works around the issue that
/// `uint8_t != unsigned char on some compilers.
template
<
class
T
,
typename
U
>
struct
is_same_ish
:
std
::
conditional
<
std
::
is_same
<
T
,
U
>::
value
,
std
::
true_type
,
is_equal_int_type
<
T
,
U
>
>::
type
{
};
/// A variant represents always a valid value of one of the types `Ts...`.
template
<
class
...
Ts
>
class
variant
{
...
...
@@ -318,6 +293,7 @@ private:
template
<
class
U
>
void
set
(
U
&&
arg
)
{
using
namespace
detail
;
using
type
=
typename
std
::
decay
<
U
>::
type
;
static
constexpr
int
type_id
=
detail
::
tl_index_where
<
...
...
libcaf_core/test/sum_type.cpp
0 → 100644
View file @
052387e7
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* 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. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE sum_type
#include "caf/test/unit_test.hpp"
#include <new>
#include <map>
#include <string>
#include "caf/default_sum_type_access.hpp"
#include "caf/detail/overload.hpp"
#include "caf/static_visitor.hpp"
#include "caf/sum_type.hpp"
#include "caf/sum_type_access.hpp"
namespace
{
struct
tostring_visitor
:
caf
::
static_visitor
<
std
::
string
>
{
template
<
class
T
>
inline
std
::
string
operator
()(
const
T
&
value
)
{
return
to_string
(
value
);
}
};
class
union_type
{
public:
friend
struct
caf
::
default_sum_type_access
<
union_type
>
;
using
T0
=
int
;
using
T1
=
std
::
string
;
using
T2
=
std
::
map
<
int
,
int
>
;
using
types
=
caf
::
detail
::
type_list
<
T0
,
T1
,
T2
>
;
union_type
()
:
index_
(
0
),
v0
(
0
)
{
// nop
}
~
union_type
()
{
destroy
();
}
template
<
class
T
>
union_type
(
T
x
)
:
union_type
()
{
*
this
=
x
;
}
union_type
&
operator
=
(
T0
value
)
{
destroy
();
index_
=
0
;
v0
=
value
;
return
*
this
;
}
union_type
&
operator
=
(
T1
value
)
{
destroy
();
index_
=
1
;
new
(
&
v1
)
T1
(
std
::
move
(
value
));
return
*
this
;
}
union_type
&
operator
=
(
T2
value
)
{
destroy
();
index_
=
2
;
new
(
&
v2
)
T2
(
std
::
move
(
value
));
return
*
this
;
}
private:
inline
union_type
&
data
()
{
return
*
this
;
}
inline
const
union_type
&
data
()
const
{
return
*
this
;
}
inline
T0
&
get
(
std
::
integral_constant
<
int
,
0
>
)
{
CAF_REQUIRE_EQUAL
(
index_
,
0
);
return
v0
;
}
inline
const
T0
&
get
(
std
::
integral_constant
<
int
,
0
>
)
const
{
CAF_REQUIRE_EQUAL
(
index_
,
0
);
return
v0
;
}
inline
T1
&
get
(
std
::
integral_constant
<
int
,
1
>
)
{
CAF_REQUIRE_EQUAL
(
index_
,
1
);
return
v1
;
}
inline
const
T1
&
get
(
std
::
integral_constant
<
int
,
1
>
)
const
{
CAF_REQUIRE_EQUAL
(
index_
,
1
);
return
v1
;
}
inline
T2
&
get
(
std
::
integral_constant
<
int
,
2
>
)
{
CAF_REQUIRE_EQUAL
(
index_
,
2
);
return
v2
;
}
inline
const
T2
&
get
(
std
::
integral_constant
<
int
,
2
>
)
const
{
CAF_REQUIRE_EQUAL
(
index_
,
2
);
return
v2
;
}
template
<
int
Index
>
inline
bool
is
(
std
::
integral_constant
<
int
,
Index
>
)
const
{
return
index_
==
Index
;
}
template
<
class
Result
,
class
Visitor
,
class
...
Ts
>
inline
Result
apply
(
Visitor
&&
f
,
Ts
&&
...
xs
)
const
{
switch
(
index_
)
{
case
0
:
return
f
(
std
::
forward
<
Ts
>
(
xs
)...,
v0
);
case
1
:
return
f
(
std
::
forward
<
Ts
>
(
xs
)...,
v1
);
case
2
:
return
f
(
std
::
forward
<
Ts
>
(
xs
)...,
v2
);
}
CAF_RAISE_ERROR
(
"invalid index in union_type"
);
}
void
destroy
()
{
if
(
index_
==
1
)
v1
.
~
T1
();
else
if
(
index_
==
2
)
v2
.
~
T2
();
}
int
index_
;
union
{
T0
v0
;
T1
v1
;
T2
v2
;
};
};
}
// namespace <anonymous>
namespace
caf
{
template
<
>
struct
sum_type_access
<
union_type
>
:
default_sum_type_access
<
union_type
>
{};
}
// namespace caf
using
namespace
caf
;
using
std
::
string
;
using
map_type
=
std
::
map
<
int
,
int
>
;
namespace
{
struct
stringify_t
{
string
operator
()(
int
x
)
const
{
return
std
::
to_string
(
x
);
}
string
operator
()(
std
::
string
x
)
const
{
return
x
;
}
string
operator
()(
const
map_type
&
x
)
const
{
return
deep_to_string
(
x
);
}
template
<
class
T0
,
class
T1
>
string
operator
()(
const
T0
&
x0
,
const
T1
&
x1
)
const
{
return
(
*
this
)(
x0
)
+
", "
+
(
*
this
)(
x1
);
}
template
<
class
T0
,
class
T1
,
class
T2
>
string
operator
()(
const
T0
&
x0
,
const
T1
&
x1
,
const
T2
&
x2
)
const
{
return
(
*
this
)(
x0
,
x1
)
+
", "
+
(
*
this
)(
x2
);
}
};
constexpr
stringify_t
stringify
=
stringify_t
{};
}
// namespace <anonymous>
CAF_TEST
(
holds_alternative
)
{
union_type
x
;
CAF_CHECK_EQUAL
(
holds_alternative
<
int
>
(
x
),
true
);
CAF_CHECK_EQUAL
(
holds_alternative
<
string
>
(
x
),
false
);
CAF_CHECK_EQUAL
(
holds_alternative
<
map_type
>
(
x
),
false
);
x
=
string
{
"hello world"
};
CAF_CHECK_EQUAL
(
holds_alternative
<
int
>
(
x
),
false
);
CAF_CHECK_EQUAL
(
holds_alternative
<
string
>
(
x
),
true
);
CAF_CHECK_EQUAL
(
holds_alternative
<
map_type
>
(
x
),
false
);
x
=
map_type
{{
1
,
1
},
{
2
,
2
}};
CAF_CHECK_EQUAL
(
holds_alternative
<
int
>
(
x
),
false
);
CAF_CHECK_EQUAL
(
holds_alternative
<
string
>
(
x
),
false
);
CAF_CHECK_EQUAL
(
holds_alternative
<
map_type
>
(
x
),
true
);
}
CAF_TEST
(
get
)
{
union_type
x
;
CAF_CHECK_EQUAL
(
get
<
int
>
(
x
),
0
);
x
=
42
;
CAF_CHECK_EQUAL
(
get
<
int
>
(
x
),
42
);
x
=
string
{
"hello world"
};
CAF_CHECK_EQUAL
(
get
<
string
>
(
x
),
"hello world"
);
x
=
map_type
{{
1
,
1
},
{
2
,
2
}};
CAF_CHECK_EQUAL
(
get
<
map_type
>
(
x
),
map_type
({{
1
,
1
},
{
2
,
2
}}));
}
CAF_TEST
(
get_if
)
{
union_type
x
;
CAF_CHECK_EQUAL
(
get_if
<
int
>
(
&
x
),
&
get
<
int
>
(
x
));
CAF_CHECK_EQUAL
(
get_if
<
string
>
(
&
x
),
nullptr
);
CAF_CHECK_EQUAL
(
get_if
<
map_type
>
(
&
x
),
nullptr
);
x
=
string
{
"hello world"
};
CAF_CHECK_EQUAL
(
get_if
<
int
>
(
&
x
),
nullptr
);
CAF_CHECK_EQUAL
(
get_if
<
string
>
(
&
x
),
&
get
<
string
>
(
x
));
CAF_CHECK_EQUAL
(
get_if
<
map_type
>
(
&
x
),
nullptr
);
x
=
map_type
{{
1
,
1
},
{
2
,
2
}};
CAF_CHECK_EQUAL
(
get_if
<
int
>
(
&
x
),
nullptr
);
CAF_CHECK_EQUAL
(
get_if
<
string
>
(
&
x
),
nullptr
);
CAF_CHECK_EQUAL
(
get_if
<
map_type
>
(
&
x
),
&
get
<
map_type
>
(
x
));
}
CAF_TEST
(
unary
visit
)
{
union_type
x
;
CAF_CHECK_EQUAL
(
visit
(
stringify
,
x
),
"0"
);
x
=
string
{
"hello world"
};
CAF_CHECK_EQUAL
(
visit
(
stringify
,
x
),
"hello world"
);
x
=
map_type
{{
1
,
1
},
{
2
,
2
}};
CAF_CHECK_EQUAL
(
visit
(
stringify
,
x
),
"[(1, 1), (2, 2)]"
);
}
CAF_TEST
(
binary
visit
)
{
union_type
x
;
union_type
y
;
CAF_CHECK_EQUAL
(
visit
(
stringify
,
x
,
y
),
"0, 0"
);
x
=
42
;
y
=
string
{
"hello world"
};
CAF_CHECK_EQUAL
(
visit
(
stringify
,
x
,
y
),
"42, hello world"
);
}
CAF_TEST
(
ternary
visit
)
{
union_type
x
;
union_type
y
;
union_type
z
;
//CAF_CHECK_EQUAL(visit(stringify, x, y, z), "0, 0, 0");
x
=
42
;
y
=
string
{
"foo"
};
z
=
map_type
{{
1
,
1
},
{
2
,
2
}};
CAF_CHECK_EQUAL
(
visit
(
stringify
,
x
,
y
,
z
),
"42, foo, [(1, 1), (2, 2)]"
);
}
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