2016-12-21 18 views
5

Bawiłem się pomysłami. Oto przykład, w którym minimalna Próbuję stworzyć koncepcję na podstawie podpisów metoda:Pojęcia: sprawdzanie podpisów metod z argumentami

template<typename T> 
concept bool myConcept() { 
    return requires(T a, int i) { 
     { a.foo() } -> int; 
     { a.bar(i) } -> int; 
    }; 
} 

struct Object { 
    int foo() {return 0;} 
    int bar(int) {return 0;} 
}; 

static_assert(myConcept<Object>(), "Object does not adhere to myConcept"); 

do mojego zaskoczenia piśmie { a.bar(int) } -> int nie działa, więc uciekają się do dodawania dodatkowy argument do wypowiedzi requires. Wydaje się to trochę dziwne i zastanawiałem się, czy istnieje sposób, aby zrobić to samo. Inną rzeczą, która zadziałała, było użycie czegoś w stylu { a.bar((int)0) } -> int, ale uważam, że jest gorsza.

Odpowiedz

6

Pojęcia sprawdzania pojęć, a a.bar(int) to nie jeden. Pisząc

{ a.foo(int) } -> int 

poprosić kompilator, aby sprawdzić, czy wspomniane wyrażenie ma typ int. Co nie ma sensu.

Znalazłeś ważną alternatywę; drugi może być, ponieważ typ a.bar(x) nie zależy x "wartości:

template<typename T> 
concept bool myConcept() { 
    return requires(T a) { 
     { a.foo() } -> int; 
     { a.bar(0) } -> int; 
    }; 
} 

struct Object { 
    int foo() {return 0;} 
    int bar(int) {return 0;} 
}; 

static_assert(myConcept<Object>(), "Object does not adhere to myConcept"); 
3

jako rzeczywista wartość typu nie ma znaczenia, ja sugeruję, używając int{} jako argument. Ta dokumentuje cel argumencie nieco lepsze, IMO:

{ a.bar(int{}) } -> int; 

Oczywiście to nie będzie działać z typów, dla których nie ma domyślnego konstruktora. W szablonach, można by użyć std::declval obejść podobny problem, ale tu błędy GCC:

error: static assertion failed: declval() must not be used! 

Ale nie ma nic, aby powstrzymać nas od pisania równoważnym (ale ZAIMPLEMENTOWANE) funkcję należy stosować z pojęciami, jak to:

#include <type_traits> 

template <class T> 
typename std::add_rvalue_reference<T>::type makeval(); 

template<typename T> 
concept bool myConcept() { 
    return requires(T a, int i) { 
     { a.foo() } -> int; 
     { a.bar(makeval<int>()) } -> int; 
    }; 
} 

struct Object { 
    int foo() {return 0;} 
    int bar(int) {return 0;} 
}; 

static_assert(myConcept<Object>(), "Object does not adhere to myConcept"); 
+0

Podoba mi się, że jesteś makevalem () i chciałbym zobaczyć go w standardzie. – YSC