Skip to content

Commit 5713032

Browse files
committed
Fixed support for incomplete types.
1 parent d550be2 commit 5713032

File tree

5 files changed

+152
-39
lines changed

5 files changed

+152
-39
lines changed

include/mpark/config.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
#define MPARK_TYPE_PACK_ELEMENT
5555
#endif
5656

57+
#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \
58+
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9)
59+
#define MPARK_CPP11_CONSTEXPR
60+
#endif
61+
5762
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
5863
#define MPARK_CPP14_CONSTEXPR
5964
#endif
@@ -85,6 +90,7 @@
8590

8691
#if !defined(__GLIBCXX__) || __has_include(<codecvt>) // >= libstdc++-5
8792
#define MPARK_TRIVIALITY_TYPE_TRAITS
93+
#define MPARK_INCOMPLETE_TYPE_TRAITS
8894
#endif
8995

9096
#endif // MPARK_CONFIG_HPP

include/mpark/lib.hpp

+120-22
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
#include "config.hpp"
1717

18-
#define MPARK_RETURN(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
18+
#define MPARK_RETURN(...) \
19+
noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
1920

2021
namespace mpark {
2122
namespace lib {
@@ -205,48 +206,107 @@ namespace mpark {
205206
static constexpr bool value = decltype(test<T>(0))::value;
206207
};
207208

208-
template <typename T, bool = is_swappable<T>::value>
209+
template <bool IsSwappable, typename T>
209210
struct is_nothrow_swappable {
210211
static constexpr bool value =
211212
noexcept(swap(std::declval<T &>(), std::declval<T &>()));
212213
};
213214

214215
template <typename T>
215-
struct is_nothrow_swappable<T, false> : std::false_type {};
216+
struct is_nothrow_swappable<false, T> : std::false_type {};
216217

217218
} // namespace swappable
218219
} // namespace detail
219220

220221
using detail::swappable::is_swappable;
221-
using detail::swappable::is_nothrow_swappable;
222+
223+
template <typename T>
224+
using is_nothrow_swappable =
225+
detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
222226

223227
// <functional>
228+
namespace detail {
229+
230+
template <typename T>
231+
struct is_reference_wrapper : std::false_type {};
232+
233+
template <typename T>
234+
struct is_reference_wrapper<std::reference_wrapper<T>>
235+
: std::true_type {};
236+
237+
template <bool, int>
238+
struct Invoke;
239+
240+
template <>
241+
struct Invoke<true /* pmf */, 0 /* is_base_of */> {
242+
template <typename R, typename T, typename Arg, typename... Args>
243+
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
244+
MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))
245+
};
246+
247+
template <>
248+
struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
249+
template <typename R, typename T, typename Arg, typename... Args>
250+
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
251+
MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))
252+
};
253+
254+
template <>
255+
struct Invoke<true /* pmf */, 2 /* otherwise */> {
256+
template <typename R, typename T, typename Arg, typename... Args>
257+
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
258+
MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))
259+
};
260+
261+
template <>
262+
struct Invoke<false /* pmo */, 0 /* is_base_of */> {
263+
template <typename R, typename T, typename Arg>
264+
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
265+
MPARK_RETURN(lib::forward<Arg>(arg).*pmo)
266+
};
267+
268+
template <>
269+
struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
270+
template <typename R, typename T, typename Arg>
271+
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
272+
MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo)
273+
};
274+
275+
template <>
276+
struct Invoke<false /* pmo */, 2 /* otherwise */> {
277+
template <typename R, typename T, typename Arg>
278+
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
279+
MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo)
280+
};
281+
282+
template <typename R, typename T, typename Arg, typename... Args>
283+
inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)
284+
MPARK_RETURN(
285+
Invoke<std::is_function<R>::value,
286+
(std::is_base_of<T, lib::decay_t<Arg>>::value
287+
? 0
288+
: is_reference_wrapper<lib::decay_t<Arg>>::value
289+
? 1
290+
: 2)>::invoke(f,
291+
lib::forward<Arg>(arg),
292+
lib::forward<Args>(args)...))
293+
224294
#ifdef _MSC_VER
225295
#pragma warning(push)
226296
#pragma warning(disable : 4100)
227297
#endif
228-
template <typename F, typename... As>
229-
inline constexpr auto invoke(F &&f, As &&... as)
230-
MPARK_RETURN(lib::forward<F>(f)(lib::forward<As>(as)...))
298+
template <typename F, typename... Args>
299+
inline constexpr auto invoke(F &&f, Args &&... args)
300+
MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))
231301
#ifdef _MSC_VER
232302
#pragma warning(pop)
233303
#endif
304+
} // namespace detail
234305

235-
template <typename B, typename T, typename D>
236-
inline constexpr auto invoke(T B::*pmv, D &&d)
237-
MPARK_RETURN(lib::forward<D>(d).*pmv)
238-
239-
template <typename Pmv, typename Ptr>
240-
inline constexpr auto invoke(Pmv pmv, Ptr &&ptr)
241-
MPARK_RETURN((*lib::forward<Ptr>(ptr)).*pmv)
242-
243-
template <typename B, typename T, typename D, typename... As>
244-
inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as)
245-
MPARK_RETURN((lib::forward<D>(d).*pmf)(lib::forward<As>(as)...))
246-
247-
template <typename Pmf, typename Ptr, typename... As>
248-
inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as)
249-
MPARK_RETURN(((*lib::forward<Ptr>(ptr)).*pmf)(lib::forward<As>(as)...))
306+
template <typename F, typename... Args>
307+
inline constexpr auto invoke(F &&f, Args &&... args)
308+
MPARK_RETURN(detail::invoke(lib::forward<F>(f),
309+
lib::forward<Args>(args)...))
250310

251311
namespace detail {
252312

@@ -296,6 +356,44 @@ namespace mpark {
296356
template <typename R, typename F, typename... Args>
297357
using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
298358

359+
namespace detail {
360+
361+
template <bool Invocable, typename F, typename... Args>
362+
struct is_nothrow_invocable {
363+
static constexpr bool value =
364+
noexcept(lib::invoke(std::declval<F>(), std::declval<Args>()...));
365+
};
366+
367+
template <typename F, typename... Args>
368+
struct is_nothrow_invocable<false, F, Args...> : std::false_type {};
369+
370+
template <bool Invocable, typename R, typename F, typename... Args>
371+
struct is_nothrow_invocable_r {
372+
private:
373+
inline static R impl() {
374+
return lib::invoke(std::declval<F>(), std::declval<Args>()...);
375+
}
376+
377+
public:
378+
static constexpr bool value = noexcept(impl());
379+
};
380+
381+
template <typename R, typename F, typename... Args>
382+
struct is_nothrow_invocable_r<false, R, F, Args...> : std::false_type {};
383+
384+
} // namespace detail
385+
386+
template <typename F, typename... Args>
387+
using is_nothrow_invocable = detail::
388+
is_nothrow_invocable<is_invocable<F, Args...>::value, F, Args...>;
389+
390+
template <typename R, typename F, typename... Args>
391+
using is_nothrow_invocable_r =
392+
detail::is_nothrow_invocable_r<is_invocable_r<R, F, Args...>::value,
393+
R,
394+
F,
395+
Args...>;
396+
299397
// <memory>
300398
#ifdef MPARK_BUILTIN_ADDRESSOF
301399
template <typename T>

test/issue.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,26 @@
77

88
#include <mpark/variant.hpp>
99

10+
#include <map>
1011
#include <memory>
1112
#include <vector>
1213

1314
#include <gtest/gtest.h>
1415

16+
#ifdef MPARK_INCOMPLETE_TYPE_TRAITS
17+
// https://github.com/mpark/variant/issues/34
18+
TEST(Issue, 34) {
19+
struct S {
20+
S(const S &) = default;
21+
S(S &&) = default;
22+
S &operator=(const S &) = default;
23+
S &operator=(S &&) = default;
24+
25+
mpark::variant<std::map<std::string, S>> value;
26+
};
27+
}
28+
#endif
29+
1530
// https://github.com/mpark/variant/pull/57
1631
TEST(Issue, 57) {
1732
std::vector<mpark::variant<int, std::unique_ptr<int>>> vec;

test/relops.cpp

+6-9
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@
1111

1212
#include <gtest/gtest.h>
1313

14-
#include "util.hpp"
14+
#include <mpark/config.hpp>
1515

16-
#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \
17-
!(__GNUC__ == 4 && __GNUC_MINOR__ == 9)
18-
#define MPARK_VARIANT_CONSTEXPR_RELOPS
19-
#endif
16+
#include "util.hpp"
2017

2118
TEST(Rel, SameTypeSameValue) {
2219
mpark::variant<int, std::string> v(0), w(0);
@@ -35,7 +32,7 @@ TEST(Rel, SameTypeSameValue) {
3532
EXPECT_TRUE(w <= v);
3633
EXPECT_TRUE(w >= v);
3734

38-
#ifdef MPARK_VARIANT_CONSTEXPR_RELOPS
35+
#ifdef MPARK_CPP11_CONSTEXPR
3936
/* constexpr */ {
4037
constexpr mpark::variant<int, const char *> cv(0), cw(0);
4138
// `cv` op `cw`
@@ -73,7 +70,7 @@ TEST(Rel, SameTypeDiffValue) {
7370
EXPECT_FALSE(w <= v);
7471
EXPECT_TRUE(w >= v);
7572

76-
#ifdef MPARK_VARIANT_CONSTEXPR_RELOPS
73+
#ifdef MPARK_CPP11_CONSTEXPR
7774
/* constexpr */ {
7875
constexpr mpark::variant<int, const char *> cv(0), cw(1);
7976
// `cv` op `cw`
@@ -111,7 +108,7 @@ TEST(Rel, DiffTypeSameValue) {
111108
EXPECT_FALSE(w <= v);
112109
EXPECT_TRUE(w >= v);
113110

114-
#ifdef MPARK_VARIANT_CONSTEXPR_RELOPS
111+
#ifdef MPARK_CPP11_CONSTEXPR
115112
/* constexpr */ {
116113
constexpr mpark::variant<int, unsigned int> cv(0), cw(0u);
117114
// `cv` op `cw`
@@ -149,7 +146,7 @@ TEST(Rel, DiffTypeDiffValue) {
149146
EXPECT_FALSE(w <= v);
150147
EXPECT_TRUE(w >= v);
151148

152-
#ifdef MPARK_VARIANT_CONSTEXPR_RELOPS
149+
#ifdef MPARK_CPP11_CONSTEXPR
153150
/* constexpr */ {
154151
constexpr mpark::variant<int, unsigned int> cv(0), cw(1u);
155152
// `cv` op `cw`

test/visit.cpp

+5-8
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,9 @@
1212

1313
#include <gtest/gtest.h>
1414

15-
#include "util.hpp"
15+
#include <mpark/config.hpp>
1616

17-
#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \
18-
!(__GNUC__ == 4 && __GNUC_MINOR__ == 9)
19-
#define MPARK_VARIANT_CONSTEXPR_VISIT
20-
#endif
17+
#include "util.hpp"
2118

2219
namespace lib = mpark::lib;
2320

@@ -45,7 +42,7 @@ TEST(Visit, ConstVarMutType) {
4542
EXPECT_EQ(ConstLRef, mpark::visit(get_qual, v));
4643
EXPECT_EQ(ConstRRef, mpark::visit(get_qual, lib::move(v)));
4744

48-
#ifdef MPARK_VARIANT_CONSTEXPR_VISIT
45+
#ifdef MPARK_CPP11_CONSTEXPR
4946
/* constexpr */ {
5047
constexpr mpark::variant<int> cv(42);
5148
static_assert(42 == mpark::get<int>(cv), "");
@@ -63,7 +60,7 @@ TEST(Visit, ConstVarConstType) {
6360
EXPECT_EQ(ConstLRef, mpark::visit(get_qual, v));
6461
EXPECT_EQ(ConstRRef, mpark::visit(get_qual, lib::move(v)));
6562

66-
#ifdef MPARK_VARIANT_CONSTEXPR_VISIT
63+
#ifdef MPARK_CPP11_CONSTEXPR
6764
/* constexpr */ {
6865
constexpr mpark::variant<const int> cv(42);
6966
static_assert(42 == mpark::get<const int>(cv), "");
@@ -89,7 +86,7 @@ TEST(Visit_Homogeneous, Double) {
8986
mpark::variant<int, std::string> v("hello"), w("world!");
9087
EXPECT_EQ("helloworld!", mpark::visit(concat{}, v, w));
9188

92-
#ifdef MPARK_VARIANT_CONSTEXPR_VISIT
89+
#ifdef MPARK_CPP11_CONSTEXPR
9390
/* constexpr */ {
9491
constexpr mpark::variant<int, double> cv(101), cw(202), cx(3.3);
9592
struct add_ints {

0 commit comments

Comments
 (0)