summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp2a/concepts-pr67148.C
blob: 97f80cfcfa861ed49bb8e35d2e4dee3118a88a31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// PR c++/67148
// { dg-do compile { target c++20 } }
// { dg-additional-options "-fconcepts-ts" }

namespace std
{
  template<typename T>
  T declval();

  typedef unsigned int size_t;
  typedef int ptrdiff_t;
  typedef decltype(nullptr) nullptr_t;
  template<typename _Tp, _Tp... _Idx>
    struct integer_sequence
    {
      typedef _Tp value_type;
      static constexpr size_t size() { return sizeof...(_Idx); }
    };

  template <class T, T Value>
  struct integral_constant {
    using type = integral_constant;
    using value_type = T;
    constexpr operator T() const { return Value; }
    constexpr T operator()() const { return Value; }
    static constexpr T value {Value};
  };
  template <class T, T Value>
  constexpr T integral_constant<T, Value>::value;
  using true_type = integral_constant<bool, true>;
  using false_type = integral_constant<bool, false>;

  template <class T, class U>
  struct is_same : false_type {};
  template <class T>
  struct is_same<T,T> : true_type {};
}
       
namespace meta
{
    inline namespace v1
    {
        template <typename T>
        using _t = typename T::type;
        template <bool... Bools>
        using and_c = std::is_same<std::integer_sequence<bool, Bools...>,
                                   std::integer_sequence<bool, (Bools || true)...>>;
    }
}

namespace stl2 { inline namespace v1 {
using std::declval;
namespace detail {
template <class...>
struct all_same : std::true_type {};
template <class T, class...Rest>
struct all_same<T, Rest...> :
  meta::and_c<__is_same_as(T, Rest)...> {};
}
template <class...Ts>
concept bool Same() {
  return detail::all_same<Ts...>::value;
}
template <class F, class...Args>
using ResultType = decltype(declval<F>()(declval<Args>()...));
template <class>
struct value_type {};
template <class T>
struct value_type<T*> {
  using type = T;
};
template <class T>
using ValueType =
  typename value_type<T>::type;

template <class F, class...Args>
concept bool Function() {
  return requires (F& f, Args&&...args) {
    f((Args&&)args...);
    requires Same<decltype(f((Args&&)args...)), ResultType<F, Args...> >();
  };
}

template <class, class...> struct __function : std::false_type {};
Function{F, ...Args} struct __function<F, Args...> : std::true_type {};

template <class F, class I1, class I2>
concept bool IndirectCallable() {
  return Function<F, ValueType<I1>, ValueType<I2>>();
}

template <class F, class I1, class I2>
concept bool IndirectCallable2() {
  return __function<F, ValueType<I1>, ValueType<I2>>::value;
}

namespace ext { namespace models {
template <class, class, class>
constexpr bool indirect_callable() { return false; }
IndirectCallable{F, I1, I2}
constexpr bool indirect_callable() { return true; }

template <class, class, class>
constexpr bool indirect_callable2() { return false; }
IndirectCallable2{F, I1, I2}
constexpr bool indirect_callable2() { return true; }
}}
}}

namespace models = stl2::ext::models;

template <class T = void>
struct plus {
  T operator()(T, T) const;
};

static_assert((models::indirect_callable<::plus<int>, int*, int*>()));
static_assert((models::indirect_callable2<::plus<int>, int*, int*>()));

static_assert((models::indirect_callable<::plus<int>, int**, int*>())); // { dg-error "static assertion failed" }
static_assert((models::indirect_callable2<::plus<int>, int**, int*>())); // { dg-error "static assertion failed" }