Skip to content

Commit

Permalink
Merge branch 'master' of github.com:pfultz2/Fit
Browse files Browse the repository at this point in the history
  • Loading branch information
pfultz2 committed Aug 30, 2015
2 parents ab86df0 + 3350297 commit 44c3336
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 30 deletions.
13 changes: 13 additions & 0 deletions fit/alias.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
/// constexpr auto alias_value(Alias&&);
///

#ifdef _MSC_VER
#pragma warning(disable: 4579)
#endif

namespace fit {

template<class T>
Expand Down Expand Up @@ -134,6 +138,15 @@ namespace detail {
template<class T, class Tag>
struct alias_static_storage
{
#ifdef _MSC_VER
// Since we disable the error for 4579 on MSVC, which leaves the static
// member unitialized at runtime, it is, therefore, only safe to use this
// class on types that are empty with constructors that have no possible
// side effects.
static_assert(std::is_empty<T>::value &&
std::is_literal_type<T>::value &&
std::is_default_constructible<T>::value, "In-class initialization is not yet implemented on MSVC");
#endif
static constexpr T value = T();
};

Expand Down
4 changes: 4 additions & 0 deletions fit/by.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ struct by_adaptor : Projection, F
return always_ref(*this)(xs...);
}

FIT_INHERIT_DEFAULT(by_adaptor, Projection, F)

template<class P, class G, FIT_ENABLE_IF_CONVERTIBLE(P, Projection), FIT_ENABLE_IF_CONVERTIBLE(G, F)>
constexpr by_adaptor(P&& p, G&& f)
: Projection(fit::forward<P>(p)), F(fit::forward<G>(f))
Expand Down Expand Up @@ -199,6 +201,8 @@ struct by_adaptor<Projection, void> : Projection
return always_ref(*this)(xs...);
}

FIT_INHERIT_DEFAULT(by_adaptor, Projection)

template<class P, FIT_ENABLE_IF_CONVERTIBLE(P, Projection)>
constexpr by_adaptor(P&& p)
: Projection(fit::forward<P>(p))
Expand Down
2 changes: 2 additions & 0 deletions fit/detail/compressed_pair.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ struct compressed_pair
: FirstBase(fit::forward<X>(x)), SecondBase(fit::forward<Y>(y))
{}

FIT_INHERIT_DEFAULT(compressed_pair, FirstBase, SecondBase)

template<class Base, class... Xs>
constexpr const Base& get_base(Xs&&... xs) const
{
Expand Down
24 changes: 19 additions & 5 deletions fit/detail/delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
#endif
#endif

#ifndef FIT_NO_STD_DEFAULT_CONSTRUCTIBLE
#if defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define FIT_NO_STD_DEFAULT_CONSTRUCTIBLE 1
#else
#define FIT_NO_STD_DEFAULT_CONSTRUCTIBLE 0
#endif
#endif

#define FIT_ENABLE_IF_CONVERTIBLE(...) \
class=typename std::enable_if<std::is_convertible<__VA_ARGS__>::value>::type

Expand All @@ -31,15 +39,17 @@
#define FIT_ENABLE_IF_CONSTRUCTIBLE(...) \
class=typename std::enable_if<std::is_constructible<__VA_ARGS__>::value>::type

#ifndef _MSC_VER
#define FIT_INHERIT_DEFAULT(C, ...) \
template<bool FitPrivateEnableBool_##__LINE__=true, \
class=typename std::enable_if<FitPrivateEnableBool_##__LINE__ && fit::detail::is_default_constructible<__VA_ARGS__>::value>::type> \
constexpr C() {}
#else
#define FIT_INHERIT_DEFAULT(C, ...) \
constexpr C() = default;
#endif

#define FIT_INHERIT_DEFAULT_EMPTY(C, ...) \
template<bool FitPrivateEnableBool_##__LINE__=true, \
class=typename std::enable_if<FitPrivateEnableBool_##__LINE__ && \
fit::detail::is_default_constructible<__VA_ARGS__>::value && std::is_empty<__VA_ARGS__>::value \
>::type> \
constexpr C() {}

#if FIT_NO_TYPE_PACK_EXPANSION_IN_TEMPLATE

Expand Down Expand Up @@ -84,7 +94,11 @@ struct is_default_constructible_helper

template<class... Xs>
struct is_default_constructible
#if FIT_NO_STD_DEFAULT_CONSTRUCTIBLE
: and_<is_default_constructible_helper<Xs>...>
#else
: and_<std::is_default_constructible<Xs>...>
#endif
{};

template<class T, class... Xs>
Expand Down
2 changes: 2 additions & 0 deletions fit/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@ struct reveal_static_const_factory
template<class F>
constexpr reveal_adaptor<F> operator=(const F& f) const
{
static_assert(is_default_constructible<F>::value, "Static functions must be default constructible");
return reveal_adaptor<F>(f);
}
#else
template<class F>
constexpr const reveal_adaptor<F>& operator=(const F&) const
{
static_assert(is_default_constructible<F>::value, "Static functions must be default constructible");
return static_const_var<reveal_adaptor<F>>();
}
#endif
Expand Down
11 changes: 11 additions & 0 deletions fit/lazy.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,18 @@ struct lazy_invoker
typedef detail::compressed_pair<F, Pack> base_type;
typedef lazy_invoker fit_rewritable1_tag;

#ifdef _MSC_VER
FIT_INHERIT_CONSTRUCTOR(lazy_invoker, base_type)
#else
FIT_INHERIT_DEFAULT_EMPTY(lazy_invoker, base_type)

template<class X, class Y,
FIT_ENABLE_IF_CONSTRUCTIBLE(base_type, X&&, Y&&)
>
constexpr lazy_invoker(X&& x, Y&& y)
: base_type(fit::forward<X>(x), fit::forward<Y>(y))
{}
#endif

template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
Expand Down
2 changes: 1 addition & 1 deletion fit/pack.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ struct pack_holder
: std::conditional<
std::is_empty<T>::value &&
std::is_literal_type<T>::value &&
is_default_constructible<T>::value,
is_default_constructible<T>::value,
alias_static<T, Tag>,
alias<T, Tag>
>
Expand Down
7 changes: 5 additions & 2 deletions fit/placeholders.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ FIT_FOREACH_UNARY_OP(FIT_UNARY_OP)
template<int N>
struct placeholder
{

#if FIT_HAS_MANGLE_OVERLOAD
template<class... Ts>
constexpr auto operator()(Ts&&... xs) const FIT_RETURNS
Expand Down Expand Up @@ -252,7 +251,11 @@ struct partial_ap
{
T val;

FIT_DELGATE_CONSTRUCTOR(partial_ap, T, val);
FIT_INHERIT_DEFAULT_EMPTY(partial_ap, T)

template<class X, class... Xs, FIT_ENABLE_IF_CONSTRUCTIBLE(T, X&&, Xs&&...)>
constexpr partial_ap(X&& x, Xs&&... xs) : val(fit::forward<X>(x), fit::forward<Xs>(xs)...)
{}

FIT_RETURNS_CLASS(partial_ap);

Expand Down
2 changes: 2 additions & 0 deletions test/by.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ FIT_TEST_CASE()
// Using mutable_ as a workaround on libc++, since mem_fn does not meet the
// requirements of a FunctionObject
FIT_TEST_CHECK(fit::by(fit::mutable_(std::mem_fn(&foo::x)), add)(foo(1), foo(2)) == 3);
static_assert(fit::detail::is_default_constructible<decltype(fit::by(select_x(), add))>::value, "Not default constructible");
}

FIT_TEST_CASE()
{
auto indirect_add = fit::by(*fit::_, fit::_ + fit::_);
FIT_TEST_CHECK(indirect_add(std::unique_ptr<int>(new int(1)), std::unique_ptr<int>(new int(2))) == 3);
static_assert(fit::detail::is_default_constructible<decltype(indirect_add)>::value, "Not default constructible");
}

struct select_x_1
Expand Down
79 changes: 57 additions & 22 deletions test/pack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,45 +128,80 @@ FIT_TEST_CASE()
// FIT_TEST_CHECK(p(deref()) == 3);
}

class empty1
struct empty1
{};

class empty2
struct empty2
{};

FIT_TEST_CASE()
{
static_assert(fit::detail::is_default_constructible<empty1, empty2>::value, "Not default constructible");
}

FIT_TEST_CASE()
{
static constexpr auto p = fit::pack(empty1());
FIT_TEST_CHECK(p(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p(fit::always(0)) == 0);
#ifndef _MSC_VER
static_assert(std::is_empty<decltype(p)>::value, "Pack not empty");
#endif
static_assert(fit::detail::is_default_constructible<decltype(p)>::value, "Not default constructible");

}

FIT_TEST_CASE()
{
static constexpr auto p1 = fit::pack(empty1());
FIT_TEST_CHECK(p1(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p1(fit::always(0)) == 0);
static constexpr auto p = fit::pack(empty1(), empty2());
FIT_TEST_CHECK(p(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p(fit::always(0)) == 0);
#ifndef _MSC_VER
static_assert(std::is_empty<decltype(p1)>::value, "Pack not empty");
static_assert(std::is_empty<decltype(p)>::value, "Pack not empty");
#endif
static_assert(fit::detail::is_default_constructible<decltype(p)>::value, "Not default constructible");
}

static constexpr auto p2 = fit::pack(empty1(), empty2());
FIT_TEST_CHECK(p2(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p2(fit::always(0)) == 0);
FIT_TEST_CASE()
{
static constexpr auto p = fit::pack(fit::pack(), fit::pack());
FIT_TEST_CHECK(p(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p(fit::always(0)) == 0);
#ifndef _MSC_VER
static_assert(std::is_empty<decltype(p2)>::value, "Pack not empty");
static_assert(std::is_empty<decltype(p)>::value, "Pack not empty");
#endif
static_assert(fit::detail::is_default_constructible<decltype(p)>::value, "Not default constructible");
}

static constexpr auto p3 = fit::pack(empty1(), empty2(), empty1());
FIT_TEST_CHECK(p3(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p3(fit::always(0)) == 0);
FIT_TEST_CASE()
{
static constexpr auto p = fit::pack(empty1(), empty2(), empty1());
FIT_TEST_CHECK(p(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p(fit::always(0)) == 0);
#ifndef _MSC_VER
static_assert(std::is_empty<decltype(p3)>::value, "Pack not empty");
static_assert(std::is_empty<decltype(p)>::value, "Pack not empty");
#endif
static_assert(fit::detail::is_default_constructible<decltype(p)>::value, "Not default constructible");
}

static constexpr auto p4 = fit::pack(empty1(), fit::pack(empty1(), empty2()));
FIT_TEST_CHECK(p4(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p4(fit::always(0)) == 0);
FIT_TEST_CASE()
{
static constexpr auto p = fit::pack(empty1(), fit::pack(empty1(), empty2()));
FIT_TEST_CHECK(p(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p(fit::always(0)) == 0);
#ifndef _MSC_VER
static_assert(std::is_empty<decltype(p4)>::value, "Pack not empty");
static_assert(std::is_empty<decltype(p)>::value, "Pack not empty");
#endif
static_assert(fit::detail::is_default_constructible<decltype(p)>::value, "Not default constructible");
}

static constexpr auto p5 = fit::pack(fit::pack(), fit::pack(fit::pack()), empty1(), fit::pack(empty1(), empty2()));
FIT_TEST_CHECK(p5(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p5(fit::always(0)) == 0);
FIT_TEST_CASE()
{
static constexpr auto p = fit::pack(fit::pack(), fit::pack(fit::pack()), empty1(), fit::pack(empty1(), empty2()));
FIT_TEST_CHECK(p(fit::always(0)) == 0);
FIT_STATIC_TEST_CHECK(p(fit::always(0)) == 0);
#ifndef _MSC_VER
static_assert(std::is_empty<decltype(p5)>::value, "Pack not empty");
static_assert(std::is_empty<decltype(p)>::value, "Pack not empty");
#endif
static_assert(fit::detail::is_default_constructible<decltype(p)>::value, "Not default constructible");
}

0 comments on commit 44c3336

Please sign in to comment.