Open5

C++コンセプト包摂関係練習帖

yohhoyyohhoy

基礎

template <typename T> concept C1 = true;
template <typename T> concept D1 = false;

namespace Q1 {
  template <typename T>
    constexpr int f(T) { return 0; }
  template <typename T> requires C1<T>
    constexpr int f(T) { return 1; }
  static_assert(f(42) == 1);
}

namespace Q2 {
  template <typename T>
    constexpr int f(T) { return 0; }
  template <typename T> requires D1<T>
    constexpr int f(T) { return 1; }
  static_assert(f(42) == 0);
}

namespace Q3 {
  template <typename T>
    constexpr int f(T) { return 0; }
  template <typename T> requires (!C1<T>)
    constexpr int f(T) { return 1; }
  static_assert(f(42) == 0);
}

namespace Q4 {
  template <typename T>
    constexpr int f(T) { return 0; }
  template <typename T> requires (!D1<T>)
    constexpr int f(T) { return 1; }
  static_assert(f(42) == 1);
}
yohhoyyohhoy

Conjunction(&&)とDisjunction(||)

template <typename T> concept C1 = true;
template <typename T> concept C2 = true;
template <typename T> concept D1 = false;
template <typename T> concept D2 = false;

namespace Q1 {
  template <typename T> requires C1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> && C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 2);
}

namespace Q2 {
  template <typename T> requires C1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> || C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q3 {
  template <typename T> requires C1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> && D2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q4 {
  template <typename T> requires C1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> || D2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q5 {
  template <typename T> requires D1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires D1<T> && C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == /*no matching*/);
}

namespace Q6 {
  template <typename T> requires D1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires D1<T> || C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 2);
}

namespace Q7 {
  template <typename T> requires C1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> && C1<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == /*ambiguous*/);
}

namespace Q8 {
  template <typename T> requires C1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> || C1<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == /*ambiguous*/);
}
yohhoyyohhoy

制約式(X && Y) || Z

template <typename T> concept C1 = true;
template <typename T> concept C2 = true;
template <typename T> concept C3 = true;
template <typename T> concept D3 = false;

namespace Q1 {
  template <typename T> requires (C1<T> && C2<T>) || C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C3<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 2);
}

namespace Q2 {
  template <typename T> requires (C1<T> && C2<T>) || C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> && C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 2);
}

namespace Q3 {
  template <typename T> requires (C1<T> && C2<T>) || C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> || C3<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q4 {
  template <typename T> requires (C1<T> && C2<T>) || C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == /*ambiguous*/);
}

namespace Q5 {
  template <typename T> requires (C1<T> && C2<T>) || D3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires D3<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q6 {
  template <typename T> requires (C1<T> && C2<T>) || D3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> || D3<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}
yohhoyyohhoy

制約式(X || Y) && Z

template <typename T> concept C1 = true;
template <typename T> concept C2 = true;
template <typename T> concept C3 = true;

namespace Q1 {
  template <typename T> requires (C1<T> || C2<T>) && C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C3<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q2 {
  template <typename T> requires (C1<T> || C2<T>) && C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires (C1<T> || C2<T>)
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q3 {
  template <typename T> requires (C1<T> || C2<T>) && C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T> && C3<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 2);
}

namespace Q4 {
  template <typename T> requires (C1<T> || C2<T>) && C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires C1<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == /*ambiguous*/);
}

namespace Q5 {
  template <typename T> requires (D1<T> || C2<T>) && C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires D1<T> || C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}

namespace Q6 {
  template <typename T> requires (D1<T> || C2<T>) && C3<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires D1<T> && C3<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}
yohhoyyohhoy

否定演算(!)と原始制約

template <typename T> concept D1 = false;
template <typename T> concept C2 = true;

namespace Q1 {
  template <typename T> requires (!D1<T>)
    constexpr int f(T) { return 1; }
  template <typename T> requires (!D1<T>) && C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == /*ambiguous*/);
}

namespace Q2 {
  template <typename T> requires (!D1<T>)
    constexpr int f(T) { return 1; }
  template <typename T> requires (!D1<T>) || C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == /*ambiguous*/);
}

template <typename T> concept NotD1 = !D1<T>;

namespace Q3 {
  template <typename T> requires NotD1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires NotD1<T> && C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 2);
}

namespace Q4 {
  template <typename T> requires NotD1<T>
    constexpr int f(T) { return 1; }
  template <typename T> requires NotD1<T> || C2<T>
    constexpr int f(T) { return 2; }
  static_assert(f(42) == 1);
}