ПрограммированиеФорумОбщее

[C++] Проверить существование типа

Страницы: 1 2 3 4 Следующая »
#0
20:53, 1 авг 2016

Нужна операция проверки существования типа, обратная enable if. То есть такое:

exists<std::enable_if_t<false>>::value //== false
exists<std::enable_if_t<true>>::value //== true

На месте std::enable_if_t может быть любой аналогичный тип, который в зависимости от аргумента шаблона существует или нет, и с ним тоже должно работать.
Возможно ли сделать это в C++?

#1
23:18, 1 авг 2016

Если тип не существует, то компилятор об этом напомнит.
Если ты боишься, что твой тип не понравится какому-то компилятору С++, то тут много решений в зависимости от причин, по которым его нет.

#2
23:34, 1 авг 2016

KKH
> Если тип не существует, то компилятор об этом напомнит.
Мне оно нужно для SFINAE, чтобы комбинировать несколько условий вместе, среди которых может быть существование типа, методов и т.п.. Вопрос существования чего угодно, да и вообще компилируемости любой синтаксической конструкции, можно свести к задаче проверки существования типа и получения булевого значения на этапе компиляции. Мне нужно решить эту задачу, и тогда все проблемы метапрограммирования будут решены.

#3
0:07, 2 авг 2016

Я предложу возможно немного громоздкий код типа такого.

#define MY_INT int
// бла бла бла
#ifdef MY_INT 
// что там хотел сделать
#endif
#4
0:15, 2 авг 2016

KKH
Это препроцессор, а надо чтобы работало при раскрытии шаблонов. В общем, я уже нашёл почти то, что нужно:
http://stackoverflow.com/questions/35661129/strange-msvc-behaviou… alis-detected
Это даже собираются добавить в стандарт, но видимо не скоро.
Но там надо заранее определять условия через using, а хотелось бы иметь возможность напрямую подставить условие в выражение. Но по крайней мере это уже лучше всего, что мне встречалось или приходило в голову самому до этого.

#5
0:40, 2 авг 2016

gammaker, извини, что умничаю, но у меня складывается впечатление, что ты усложняешь там, где в этом нет необходимости. Ты программу так строишь, что возможны такие ситуации, что возможен вызов или объявление переменных типами, которых не существует. Тут мне кажется "игры разума". В любом случае компилятор должен впихнуть такой кусок кода в откомпилированный бинарник, который бы знал с чем сравнивать и если программа написана так, что компилятор знает с чем сравнить и ответ False, то это могло произойти только если так написана и откомпилирована программа. Если же в бинарнике попадётся код сравнения чего-то известного с неизвестным - то программа должна слететь.
И получив свой метод ты будешь гадать дальше: как быть - сравнить известный тип с неизвестным. Или почему в одних случаях программа вылетает с крашем а в других нет, хотя код отличается буквально на объявление одного типа который нигде не используется. А ответ таков: ты наипал компилятор и он выдал нерабочий бинарник.
Извини за такой комментарий наезд. Но как программист профи ты должен писать сверх надёжный код, который не должен никогда слетать.

#6
13:20, 2 авг 2016

KKH
> Ты программу так строишь, что возможны такие ситуации, что возможен вызов или
> объявление переменных типами, которых не существует.
Так программу строят все, кто использует шаблоны на уровне чуть выше начинающего. Особенно те, кто пишет библиотеки общего назначения типа STL\Boost.
Смысл в том, чтобы при передачи в шаблонную функцию объектов эта шаблонная функция могла принять объекты только тех типов, которые реализуют нужные методы и операторы. Если передали объект не подходящего типа, при раскрытии шаблона функции начнутся громоздкие и тяжело читаемые ошибки компиляции. Поэтому делают дополнительные проверки так, чтобы компилятор не раскрывал шаблон функции, а сразу сказал, что с таким типом функцию инстанциировать невозможно. Особенно это актуально, когда для разных условий нужны разные функции. Приходится делать шаблонную перегрузку и без проверок компилятор просто не будет знать, какую из этих перегрузок вызывать. Если сделать так, что для одних типов существует одна перегрузка с одним условием, а для типов с другим условием существует другая одна перегрузка, то компилятор вызовет ту, которая существует.
Но сам язык C++ не предусматривает возможности делать такие проверки, поэтому извращаются тем, что эксплуатируют такую особенность языка: если произошла ошибка подстановки в прототип функции, то она не компилируется. А для этого специально делают типы, которые существуют при выполнении некоторого условия и не существуют при невыполнении этого условия. Даже в стандартной библиотеке C++ есть целый набор таких извращений в заголовочном файле <type_traits>, в частности enable_if. По условию создать такой условно существующий тип легко, а вот у меня встала задача сделать наоборот. В стандартной библиотеке нет такого решения, хотя вроде собираются добавить в будущем.

KKH
> Или почему в одних случаях программа вылетает с крашем а в других нет, хотя код
> отличается буквально на объявление одного типа который нигде не используется. А
> ответ таков: ты наипал компилятор и он выдал нерабочий бинарник.
Ну не понимаешь ты SFINAE. Я тоже раньше не понимал, пока не пришлось разобраться. Эти манипуляции все происходят на этапе компиляции. И речь здесь не об обмане компилятора. Если у него будет хоть малейшая неясность с типами до создания бинарника дело просто не дойдёт. Просто язык не предоставляет некоторых нужных мне возможностей, а я всякими ухищрениями пытаюсь их реализовать через то, что есть в языке. Сами реализации ухищрений выглядят как говно, но их использование довольно просто и понятно.

#7
13:54, 2 авг 2016

В виде нестандартного расширения MSVC++ да, существует. https://msdn.microsoft.com/en-us/library/x7wy9xh3.aspx

#8
14:46, 2 авг 2016

odino4ka
> В виде нестандартного расширения MSVC++ да, существует.
> https://msdn.microsoft.com/en-us/library/x7wy9xh3.aspx
Да, я знаю. Я уже нашёл универсальное решение, которое работает в 2015 студии и Clang и вроде как по стандарту корректно, но в 2013 студии не работает. Специально для неё пытаюсь через это расширение сделать проверку, но нужно её спрятать за тем же интерфейсом, что и универсальный способ. Но что-то не получается пока. Похоже, как будто ни __if_exists, ни __if_not_exists с одним и тем же условием не срабатывают.
А вообще это расширение - штука полезная. Даже в очень старой студии с ним можно реализовать if constexpr из будущего стандарта, который пока появился только в Clang 3.9.

#9
15:19, 2 авг 2016

да, пользоваться этим прикольно. а вот ковырять такой код наркоманский - сущий ад :)

#10
21:26, 2 авг 2016

gammaker
> Нужна операция проверки существования типа, обратная enable if.
std::enable_if не проверяет существование типа, а

используется для условного удаления функций и классов, основываясь на статической диагностике типов (type traits)

А чем не устраивает:

std::enable_if<!FLAG>::type

?

#11
21:42, 2 авг 2016

Adler
> std::enable_if не проверяет существование типа
Вот именно. Она в зависимости от булевого условия даёт либо существующий тип, либо не существующий, последствием чего является удаление или не удаление функций. А мне нужно ровно наоборот: если тип существует - получить true, а если нет - false. Чтобы потом этот результат можно было объединить с другими условиями и запихнуть уже в enable_if.

#12
22:11, 2 авг 2016

gammaker
Что значит "существание типа"? Декларация или определение? Использовать незадекларированный тип нельзя нигде.

#13
22:22, 2 авг 2016

- Нужна операция проверки существования файла, обратная std::ostream::seekp
- std::ostream::seekp не проверяет существование файла.
- Вот именно.

#14
22:35, 2 авг 2016

PANDA
> Что значит "существание типа"? Декларация или определение? Использовать
> незадекларированный тип нельзя нигде.
Ну я же написал в #0. Нужен шаблон, в который можно параметром передать enable_if_t<false> и получить false, а если передать enable_if_t<true>, int или ещё какой-нибудь определённый тип, то получить true. То есть как бы тип объявлен, но конкретной инстанциации для него может не быть. И нужно узнать, есть она или нет.

Adler
> - Нужна операция проверки существования файла, обратная std::ostream::seekp
Не знаю, к чему ты привёл эту неаналогичную аналогию. Эти операции не обратны друг другу в отличие от тех, про которые я говорил.

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорумОбщее