Skip to content

Commit

Permalink
Fix bug with sfinae id of rank
Browse files Browse the repository at this point in the history
  • Loading branch information
pfultz2 committed Oct 31, 2015
1 parent 9b9326f commit 9b18f5e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 22 deletions.
31 changes: 9 additions & 22 deletions fit/conditional.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,33 +89,20 @@ struct rank<0>
template<int N, class...Fs> struct conditional_adaptor_base;

template<int N, class F, class...Fs>
struct conditional_adaptor_base<N, F, Fs...> : F, conditional_adaptor_base<N-1, Fs...>
struct conditional_adaptor_base<N, F, Fs...> : conditional_adaptor_base<N, F>, conditional_adaptor_base<N-1, Fs...>
{
typedef conditional_adaptor_base<N-1, Fs...> base;
typedef conditional_adaptor_base<N, F> single_base;

FIT_INHERIT_DEFAULT(conditional_adaptor_base, F, base);
FIT_INHERIT_DEFAULT(conditional_adaptor_base, single_base, base);

template<class X, class... Xs, FIT_ENABLE_IF_CONVERTIBLE(X, F), FIT_ENABLE_IF_CONSTRUCTIBLE(base, Xs...)>
template<class X, class... Xs, FIT_ENABLE_IF_CONVERTIBLE(X, single_base), FIT_ENABLE_IF_CONSTRUCTIBLE(base, Xs...)>
constexpr conditional_adaptor_base(X&& f1, Xs&& ... fs)
: F(fit::forward<X>(f1)), base(fit::forward<Xs>(fs)...)
: single_base(fit::forward<X>(f1)), base(fit::forward<Xs>(fs)...)
{}

using base::operator();

template<class... Ts>
constexpr const F& base_function(Ts&&... xs) const
{
return always_ref(*this)(xs...);
}

FIT_RETURNS_CLASS(conditional_adaptor_base);

template<class... Ts>
constexpr FIT_SFINAE_RESULT(const F&, id_<Ts>...)
operator()(rank<N>, Ts&&... xs) const FIT_SFINAE_RETURNS
(
(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)))(fit::forward<Ts>(xs)...)
);
using single_base::operator();
};

template<int N, class F>
Expand Down Expand Up @@ -149,7 +136,7 @@ struct conditional_adaptor
{
typedef conditional_adaptor fit_rewritable_tag;
typedef detail::conditional_adaptor_base<sizeof...(Fs), Fs...> base;
typedef detail::rank<sizeof...(Fs)> rank;
typedef detail::rank<sizeof...(Fs)> rank_type;

FIT_INHERIT_CONSTRUCTOR(conditional_adaptor, base);

Expand All @@ -166,10 +153,10 @@ struct conditional_adaptor
FIT_RETURNS_CLASS(conditional_adaptor);

template<class... Ts>
constexpr FIT_SFINAE_RESULT(const base&, rank, id_<Ts>...)
constexpr FIT_SFINAE_RESULT(const base&, id_<rank_type>, id_<Ts>...)
operator()(Ts&&... xs) const FIT_SFINAE_RETURNS
(
(FIT_MANGLE_CAST(const base&)(FIT_CONST_THIS->base_function(xs...)))(rank(), fit::forward<Ts>(xs)...)
(FIT_MANGLE_CAST(const base&)(FIT_CONST_THIS->base_function(xs...)))(rank_type(), fit::forward<Ts>(xs)...)
);
};

Expand Down
69 changes: 69 additions & 0 deletions test/is_callable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
#include <ciso646>
#include "test.h"

template<int N>
struct callable_rank : callable_rank<N-1>
{};

template<>
struct callable_rank<0>
{};

FIT_STATIC_TEST_CASE()
{
Expand All @@ -17,16 +24,78 @@ FIT_STATIC_TEST_CASE()
{
}

struct is_callable_rank_class
{
void operator()(int, callable_rank<3>) const
{
}

void operator()(int, callable_rank<4>) const
{
}
};

static_assert(fit::is_callable<is_callable_class, int>::value, "Not callable");
static_assert(fit::is_callable<is_callable_class, long>::value, "Not callable");
static_assert(fit::is_callable<is_callable_class, double>::value, "Not callable");
static_assert(fit::is_callable<is_callable_class, const int&>::value, "Not callable");
static_assert(fit::is_callable<is_callable_class, const long&>::value, "Not callable");
static_assert(fit::is_callable<is_callable_class, const double&>::value, "Not callable");
static_assert(not fit::is_callable<is_callable_class, callable_test_param>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_class>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_class, int, int>::value, "callable failed");

typedef void (*is_callable_function_pointer)(int);
static_assert(fit::is_callable<is_callable_function_pointer, int>::value, "Not callable");
static_assert(fit::is_callable<is_callable_function_pointer, long>::value, "Not callable");
static_assert(fit::is_callable<is_callable_function_pointer, double>::value, "Not callable");
static_assert(fit::is_callable<is_callable_function_pointer, const int&>::value, "Not callable");
static_assert(fit::is_callable<is_callable_function_pointer, const long&>::value, "Not callable");
static_assert(fit::is_callable<is_callable_function_pointer, const double&>::value, "Not callable");
static_assert(not fit::is_callable<is_callable_function_pointer, callable_test_param>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_function_pointer>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_function_pointer, int, int>::value, "callable failed");

static_assert(fit::is_callable<is_callable_rank_class, int, callable_rank<3>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, long, callable_rank<3>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, double, callable_rank<3>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const int&, callable_rank<3>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const long&, callable_rank<3>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const double&, callable_rank<3>>::value, "Not callable");

static_assert(fit::is_callable<is_callable_rank_class, int, callable_rank<4>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, long, callable_rank<4>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, double, callable_rank<4>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const int&, callable_rank<4>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const long&, callable_rank<4>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const double&, callable_rank<4>>::value, "Not callable");

static_assert(fit::is_callable<is_callable_rank_class, int, callable_rank<5>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, long, callable_rank<5>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, double, callable_rank<5>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const int&, callable_rank<5>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const long&, callable_rank<5>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const double&, callable_rank<5>>::value, "Not callable");

static_assert(fit::is_callable<is_callable_rank_class, int, callable_rank<6>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, long, callable_rank<6>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, double, callable_rank<6>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const int&, callable_rank<6>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const long&, callable_rank<6>>::value, "Not callable");
static_assert(fit::is_callable<is_callable_rank_class, const double&, callable_rank<6>>::value, "Not callable");

static_assert(not fit::is_callable<is_callable_rank_class, int, callable_rank<1>>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, long, callable_rank<1>>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, double, callable_rank<1>>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, const int&, callable_rank<1>>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, const long&, callable_rank<1>>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, const double&, callable_rank<1>>::value, "callable failed");

static_assert(not fit::is_callable<is_callable_rank_class, callable_test_param, callable_test_param>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, callable_rank<3>, callable_test_param>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, callable_rank<4>, callable_test_param>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, callable_test_param, callable_rank<3>>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, callable_test_param, callable_rank<4>>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class>::value, "callable failed");
static_assert(not fit::is_callable<is_callable_rank_class, int, int>::value, "callable failed");
};

0 comments on commit 9b18f5e

Please sign in to comment.