В этом вопросе действительно нет фона.SFINAE для пользовательского преобразования
Существует много способов использования SFINAE (прямо или косвенно с type_traits) для проверки существующей функции, функции-члена и т. Д. Но:
Первый вопрос: Есть ли способ проверить, реализует ли класс определенный пользовательский оператор преобразования?
Чтобы проиллюстрировать, что я имею в виду, рассмотрим этот код. Я хотел бы запустить этот код без утверждения провал попытки:
#include <type_traits>
#include <cassert>
struct NotADouble {
};
struct Double {
// explicit or not - you decide
explicit operator double() {
return 1.;
}
};
// CORRECT THIS: ...
template<typename T,
class = decltype(static_cast<double>(std::declval<T>()))>
int f(T) {
return 1;
}
int f(...) {
return 2;
}
// ... UNTIL HERE
int main() {
assert(f(NotADouble()) == 2);
assert(f(Double()) == 1);
assert(f(3.) == 2);
assert(f(3) == 2);
assert(f(3.f) == 2);
}
Текущая реализация f
проверяет, есть ли стандартная последовательность преобразования из T
в double
, я предполагаю, что это то же самое, как std::is_convertible
в этом случае.
Другим подходом будет следующая реализация, которая принимает первые два теста.
template<typename T>
int f(T, double (T::*)() = nullptr) {
return 1;
}
int f(...) {
return 2;
}
Вопрос 2: Несмотря на то, NotADouble не реализует какой-либо оператор преобразования, по-видимому, чтобы эту функцию указателя. Итак, что же такое double (T::*)()
и почему оно существует для любого класса?
Был аналогичный тест, который я пробовал, но без ссылки, чего явно не хватало ... – overseas
@ user3445587 Вы имеете в виду оператор 'address of' (&). Да, к сожалению, нет способа взять ссылку на функцию-член, что явно является недостатком, но оно напрямую связано с синтаксисом вызова метода C++. Например. в 'a.foo();' как 'foo' следует интерпретировать? В качестве функции-члена функции 'a' или ссылки функции-члена доступны в области ...? –