В MSVC2017 это работает нормально, оба static_asserts НЕ запускаются, как ожидалось:
template <typename T>
struct do_have_size {
template <typename = decltype(std::declval<T>().size())>
static std::true_type check(T);
static std::false_type check(...);
using type = decltype(check(std::declval<T>()));
};
int main() {
using TR = typename do_have_size<std::vector<int>>::type;
using FL = typename do_have_size<int>::type;
static_assert(std::is_same<TR, std::true_type>::value, "TRUE");
static_assert(std::is_same<FL, std::false_type>::value, "FALSE");
}
Однако, если я скомпилирую в g++ 7.1 или clang 4.0, я получаю следующую ошибку компилятора:
In instantiation of 'struct do_have_size<int>':
20:39: required from here
9:24: error: request for member 'size' in 'declval<do_have_size<int>::TP>()', which is of non-class type 'int'
По моему пониманию SFINAE, подстановка функции возврата true_type
должна прерываться для параметра int
, и следующая функция должна быть выбрана, как это сделано в MSVC. Почему clang и g++ вообще не компилируют его?
Я скомпилирован только с -std=c++17
, возможно, что-то еще нужно?