Обнаружение поддержки оператора с помощью decltype / SFINAE

StackOverflow https://stackoverflow.com/questions/5839357

  •  27-10-2019
  •  | 
  •  

Вопрос

В (несколько) устаревшей статье рассматриваются способыиспользуйте decltype вместе с SFINAE, чтобы определить, поддерживает ли тип определенные операторы, такие как == или <.

Вот пример кода, чтобы определить, поддерживает ли класс оператор <:

родовое слово

Это выводит true, поскольку, конечно, std::string поддерживает оператор <.Однако, если я попытаюсь использовать его с классом, который не поддерживает оператор <, я получаю ошибку компилятора:

родовое слово

Значит, СФИНАЭ здесь не работает.Я пробовал это на GCC 4.4 и GCC 4.6, и оба показали одинаковое поведение.Итак, можно ли использовать SFINAE таким образом, чтобы определить, поддерживает ли тип определенные выражения?

Это было полезно?

Решение

Вам необходимо сделать вашу функцию less_than_test шаблоном, поскольку SFINAE означает «Ошибка подстановки не является ошибкой», и в вашем коде нет функции шаблона, которая может вызвать сбой при выборе.

родовое слово

Другие советы

В C ++ 11 самым коротким и общим решением, которое я нашел, было следующее:

родовое слово

Работает с g++ 4.8.1 и clang++ 3.3


Более общее решение для произвольных операторов (ОБНОВЛЕНИЕ 2014 г.)

Существует более общее решение, использующее тот факт, что все встроенные операторы также доступны (и, возможно, специализированы) через оболочки операторов STD, такие как std::less (двоичный) или std::negate (унарный).

родовое слово

Это можно использовать в самом общем виде, особенно в C ++ 14, где определение типа откладывается до вызова оболочки оператора («прозрачные операторы»).

Для бинарных операторов это может использоваться как:

родовое слово

Для унарных операторов:

родовое слово

(Со стандартной библиотекой C ++ 11 все немного сложнее, потому что нет сбоев при установке decltype(std::less<random_type>()(...)), даже если для random_type не определена операция, можно вручную реализовать прозрачные операторы в C ++ 11, которые являются стандартными в C ++ 14)

Синтаксис довольно плавный. Надеюсь, что-то подобное будет принято в стандарте.


Два расширения:

1) Он работает для обнаружения приложений с исходными функциями:

родовое слово

2) Он может дополнительно определить, является ли результат конвертируемым / сопоставимым с определенным типом, в этом случае поддерживается double < double, но будет возвращено значение false во время компиляции, потому что результат не указан.

родовое слово

Примечание: я только что попытался скомпилировать код с C ++ 14 в http:// melpon.org/wandbox/ , и это не сработало. Я думаю, что есть проблема с прозрачными операторами (такими как std::less<>) в этой реализации (clang ++ 3.5 c ++ 14), поскольку когда я реализую свой собственный less<> с автоматическим выводом, он работает хорошо.

Это C ++ 0x, нам больше не нужны трюки, основанные на генерации кода тегов ...; -]

родовое слово

(Это основано на ответе iammilind, но не требует, чтобы тип возвращаемого значения sizeof был другого размера, чем T, и не требует, чтобы operator< создавался по умолчанию.)

Ниже приведен простой код, удовлетворяющий вашим требованиям (если вы не хотите ошибки компиляции):

родовое слово

Использование:

родовое слово

[Примечание: если вам нужна ошибка компиляции для классов, не имеющих кода operator <, это очень легко сгенерировать с помощью очень небольшого количества строк кода.]

@xDD действительно правильный, хотя его пример немного ошибочен.

Это компилируется на идеоне:

родовое слово

Результат:

родовое слово

См. здесь в действии.

Дело в том, что SFINAE применяется только к функциям шаблона.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top