Skip to content

Commit

Permalink
Merge branch 'implicit' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
pfultz2 committed Jan 30, 2017
2 parents 43a9369 + 86aee9d commit 9df33a4
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 29 deletions.
66 changes: 37 additions & 29 deletions include/fit/implicit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,45 +100,53 @@ struct is_implicit_callable<F, Pack, X, typename std::enable_if<
: std::true_type
{};
#endif
template<template <class...> class F, class Pack>
struct implicit_invoke
{
Pack p;

constexpr implicit_invoke(Pack pp) : p(pp)
{}

template<class X, class=typename std::enable_if<is_implicit_callable<F<X>, Pack, X>::value>::type>
constexpr operator X() const
{
return p(F<X>());
}

template<template <class...> class F2, class Pack2>
constexpr operator implicit_invoke<F2, Pack2>() const
{
return implicit_invoke<F2, Pack2>(p);
}
};

template<template <class...> class F, class Pack>
constexpr implicit_invoke<F, Pack> make_implicit_invoke(Pack&& p)
{
return implicit_invoke<F, Pack>(FIT_FORWARD(Pack)(p));
}

}


template<template <class...> class F>
struct implicit
{
template<class Pack>
struct invoker
{
Pack p;

constexpr invoker(Pack pp) FIT_NOEXCEPT_CONSTRUCTIBLE(Pack, Pack&&)
: p(fit::move(pp))
{}

template<class X, class=typename std::enable_if<detail::is_implicit_callable<F<X>, Pack, X>::value>::type>
constexpr operator X() const FIT_NOEXCEPT(noexcept(p(F<X>())))
{
return p(F<X>());
}
#if !(defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
invoker (const invoker&) = delete;
invoker& operator= (const invoker&) = delete;

private:
friend struct implicit;
invoker (invoker&&) = default;
#endif
};

struct make_invoker
{
template<class Pack>
constexpr invoker<Pack> operator()(Pack p) const FIT_NOEXCEPT(noexcept(invoker<Pack>(fit::move(p))))
{
return invoker<Pack>(fit::move(p));
}

};

template<class... Ts>
constexpr auto operator()(Ts&&... xs) const FIT_RETURNS
constexpr auto operator()(Ts&&... xs) const
FIT_RETURNS
(
detail::make_implicit_invoke<F>(fit::pack_basic(FIT_FORWARD(Ts)(xs)...))
FIT_RETURNS_CONSTRUCT(make_invoker)()(fit::pack_basic(FIT_FORWARD(Ts)(xs)...))
);

};

} // namespace fit
Expand Down
22 changes: 22 additions & 0 deletions test/fail/implicit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <fit/implicit.hpp>

template<class T>
struct auto_caster
{
template<class U>
T operator()(U x)
{
return T(x);
}
};


int main()
{
fit::implicit<auto_caster> auto_cast = {};
auto x = auto_cast(1.5);
(void)x;
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
static_assert(false, "Always fail");
#endif
}
18 changes: 18 additions & 0 deletions test/implicit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ struct auto_caster
}
};

template<class T>
struct auto_caster_noexcept
{
template<class U>
T operator()(U x) noexcept
{
return T(x);
}
};

struct auto_caster_foo
{
int i;
Expand All @@ -30,3 +40,11 @@ FIT_TEST_CASE()
FIT_TEST_CHECK(1 == x.i);

}
#if FIT_HAS_NOEXCEPT_DEDUCTION
FIT_TEST_CASE()
{
fit::implicit<auto_caster_noexcept> lauto_cast{};
float f = 1.5;
static_assert(noexcept(int(lauto_cast(f))), "noexcept implicit");
}
#endif

0 comments on commit 9df33a4

Please sign in to comment.