Viewing file: generic-fn.C (3.06 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
// { dg-do compile { target c++17_only } } // { dg-options "-fconcepts" }
#include <cassert> #include <type_traits>
template<typename T> concept bool C() { return __is_class(T); }
template<typename T> concept bool Type() { return true; }
struct S { };
int called;
// Basic terse notation void f(auto x) { called = 1; } void g(C x) { called = 2; }
// Overloading generic functions void h(auto x) { called = 1; } void h(C x) { called = 2; }
void p(auto x); void p(C x);
struct S1 { void f1(auto x) { called = 1; } void f2(C x) { called = 2; }
void f3(auto x) { called = 1; } void f3(C x) { called = 2; } };
template<C T> struct S2 { void f1(auto x) { called = 1; } void f2(C x) { called = 2; }
void f3(auto x) { called = 1; } void f3(C x) { called = 2; }
void h1(auto x); void h2(C x);
void h3(auto x); void h3(C x);
template<C U> void g1(T t, U u) { called = 1; }
template<C U> void g2(T t, U u); };
void ptr(C*) { called = 1; } void ptr(const C*) { called = 2; }
void ref(C&) { called = 1; } void ref(const C&) { called = 2; }
void fwd_lvalue_ref(Type&& x) { using T = decltype(x); static_assert(std::is_lvalue_reference<T>::value, "not an lvlaue reference"); }
void fwd_const_lvalue_ref(Type&& x) { using T = decltype(x); static_assert(std::is_lvalue_reference<T>::value, "not an lvalue reference"); using U = typename std::remove_reference<T>::type; static_assert(std::is_const<U>::value, "not const-qualified"); }
void fwd_rvalue_ref(Type&& x) { using T = decltype(x); static_assert(std::is_rvalue_reference<T>::value, "not an rvalue reference"); }
// Make sure we can use nested names speicifers for concept names. namespace N { template<typename T> concept bool C() { return true; } } // namesspace N
void foo(N::C x) { }
int main() { S s; const S cs;
f(0); assert(called == 1); g(s); assert(called == 2);
h(0); assert(called == 1); h(s); assert(called == 2);
S1 s1; s1.f1(0); assert(called == 1); s1.f2(s); assert(called == 2);
s1.f3(0); assert(called == 1); s1.f3(s); assert(called == 2);
S2<S> s2; s2.f1(0); assert(called == 1); s2.f2(s); assert(called == 2);
s2.f3(0); assert(called == 1); s2.f3(s); assert(called == 2);
s2.h1(0); assert(called == 1); s2.h2(s); assert(called == 2);
s2.h3(0); assert(called == 1); s2.h3(s); assert(called == 2);
s2.g1(s, s); assert(called == 1); s2.g2(s, s); assert(called == 2);
ptr(&s); assert(called == 1); ptr(&cs); assert(called == 2);
ref(s); assert(called == 1); ref(cs); assert(called == 2);
// Check forwarding problems fwd_lvalue_ref(s); fwd_const_lvalue_ref(cs); fwd_rvalue_ref(S());
foo(0); }
// Test that decl/def matching works.
void p(auto x) { called = 1; } void p(C x) { called = 2; }
template<C T> void S2<T>::h1(auto x) { called = 1; }
template<C T> void S2<T>::h2(C x) { called = 2; }
template<C T> void S2<T>::h3(auto x) { called = 1; }
template<C T> void S2<T>::h3(C x) { called = 2; }
template<C T> template<C U> void S2<T>::g2(T t, U u) { called = 2; }
|