Изменить, чтобы избежать путаницы:
decltype
не принимает два аргумента. См. Ответы.
Следующие две структуры могут использоваться для проверки существования функции-члена в типе T
во время компиляции:
// Non-templated helper struct:
struct _test_has_foo {
template<class T>
static auto test(T* p) -> decltype(p->foo(), std::true_type());
template<class>
static auto test(...) -> std::false_type;
};
// Templated actual struct:
template<class T>
struct has_foo : decltype(_test_has_foo::test<T>(0))
{};
Я думаю, что идея заключается в использовании SFINAE при проверке существования функции-члена, поэтому в случае, если p->foo()
недействителен, определена только версия эллипсов test
, которая возвращает std::false_type
. В противном случае первый метод будет определен для T*
и вернет std::true_type
. Фактический "переключатель" происходит во втором классе, который наследуется от типа, возвращаемого test
. Это кажется умным и "легким" по сравнению с разными подходами с is_same
и тому подобным.
decltype
с двумя аргументами сначала выглядел удивительно для меня, так как я думал, что он просто получает тип выражения. Когда я увидел код выше, я подумал, что это похоже на "попытаться скомпилировать выражения и всегда возвращать тип второго. Сбой, если выражения не скомпилируются" (так что скрыть эту специализацию: SFINAE).
Но:
Затем я подумал, что могу использовать этот метод для записи любой проверки "допустимого выражения", если это зависит от некоторого типа T
. Пример:
...
template<class T>
static auto test(T* p) -> decltype(bar(*p), std::true_type());
...
Это, как я думал, вернет a std::true_type
тогда и только тогда, когда определено bar
, принимающее T
в качестве первого параметра (или если T
является конвертируемым и т.д.), то есть: если bar(*p)
будет компилироваться, если он был написан в некотором контексте, где p
определяется типа T*
.
Однако приведенная выше модификация всегда оценивается до std::false_type
. Почему это? Я не хочу исправлять его с помощью некоторого сложного кода. Я просто хочу знать, почему это не работает, как я ожидал. Ясно, что decltype
с двумя аргументами работает не так, как я думал. Я не мог найти никакой документации; это объясняется только одним выражением.