Проблема в том, что VC ++ 2010 обрабатывает метафункцию is_less_than_comparable
, а не static_assert
.
Если вы измените код на:
static const bool value = std::is_same<double, decltype(test<T>(true))>::value;
Тогда это будет ложнымнезависимо от того, какая перегрузка выбрана.Затем срабатывает утверждение.
Очевидно, выбрана неправильная перегрузка, SFINAE не удаляет кандидата с типом возврата char
.
Более простой тест (неправильно печатается 1
):
#include <type_traits>
template<typename T> struct is_less_than_comparable {
template<typename Test> static char test(decltype(*static_cast<Test*>(nullptr) < *static_cast<Test*>(nullptr)) b);
template<typename Test> static int test(...);
static const bool value = std::is_same<char, decltype(test<T>(true))>::value;
};
struct x {};
#include <iostream>
int main() {
std::cout << is_less_than_comparable<x>::value << std::endl;
}
Компилятор без видимой причины предоставляет оператор bool operator<(x, x)
, таким образом генерирует int is_less_than_comparable<T>::test<T>(bool)
.Если задан пользовательский оператор сравнения, его тип возвращаемого значения выбран правильно.Этот оператор не входит с одним из заголовков, я могу воспроизвести decltype
с разрешением bool
без заголовков.
Это приводит к соответствующей ошибке:
decltype(*(x*)nullptr < *(x*)nullptr) b;
error C2676: binary '<' : 'x' does not define this operator or a conversion to a type acceptable to the predefined operator
Я думаю, это связано с тем, что VC ++ не выполняет двухфазный поиск аргументов, зависящих от шаблона.