Рассмотрим следующий пример:Обратный тип возврата, декларационные и контрольные квалификаторы: могут ли они работать вместе?
#include <utility>
struct A { void f() {} };
struct B { void f() & {} };
struct C { void f() && {} };
template<typename T>
auto f() -> decltype(std::declval<T>().f())
{}
int main() {
f<A>();
// f<B>(); // (*)
f<C>();
}
При вызове с B
(строка (*)
), код не компилируется больше для std::declval
преобразует T
к опорным Rvalue типа в конкретном случае.
Если мы изменим его немного, как это следует, мы имеем противоположную проблему:
// ...
template<typename T>
auto f() -> decltype(std::declval<T&>().f())
{}
// ...
int main() {
f<A>();
f<B>();
// f<C>(); // (*)
}
Теперь линия (*)
не будет работать для std::declval
преобразующего типа к Lvalue ссылочного типа в конкретном случае.
Есть ли способ определить выражение, которое принимает тип T
, если он имеет функцию-член f
, независимо от того, каков его ссылочный классификатор?
У меня нет никакого реального дела, в котором я хотел бы использовать это, и я не могу делать какие-либо реальный пример использования.
Этот вопрос ради любопытства, не более того.
Я понимаю, что есть причина, если есть ref-qualifier, и я не должен пытаться сломать дизайн класса.
Как насчет 'decltype (& T :: е)'? – Brian
Не будет работать для перегруженных 'f' – krzaq
@Brian Ну, это сработает в этом минимальном примере, но это не сработает, если у вас есть аргументы, которые будут использоваться в _invokation_. – skypjack