Мой вариант, распознает корректо. Рекомендую вам также использовать идиому упрятывания оригинального типа в объект.
Есть несколько вариантов, вот, к примеру, еще один:
D> Возвращается указатель!!! Однако T выводится как массив! D> Предлагаю использовать это
Т.е. если размер типа не равен оному после пропуска через такую функцию — это якобы массив.
А если sizeof(T[]) == sizeof(T*) ?
Например, char * и char[4].
Здравствуйте, Andrew S, Вы писали:
AS>Т.е. если размер типа не равен оному после пропуска через такую функцию — это якобы массив. AS>А если sizeof(T[]) == sizeof(T*) ? AS>Например, char * и char[4].
В общем, теперь, я признаюсь, мне разонравилась идея сравнивания посредством размеров. Слишком, геморрой развивает. Особенно, если типы-параметры можно просто сравнить. Например, так:
Здравствуйте, Denn, Вы писали:
D> Про задачу определения массив или не массив. Код я опубликую в следующем посте, но настоятельно рекомендую порешать эту задачу самому. Вы можете получить просто не детское удовольствие решив ее!!!
D> Смотрите, пусть у нас есть шаблонная функция. Например:
D> D>
D> Возвращается указатель!!! Однако T выводится как массив! D> Предлагаю использовать это
Любое решение, основанное на этом принципе, будет обладать огромным недостатком, фактически делающим это решение неприемлемым. Это поведение является эксклюзивным для MSVC++ и не имеет места в стандартном компиляторе. Другими словами, это поведение является багом/расширением MSVC++. При использовании стандартного компилятора подобный код вызовет ошибку компиляции с сообщением о том, что функция не может возвращать результат типа "массив". Мое решение таким недостатком не обладает и использует только стандартное подмножество свойств компилятора MSVC++.
Код будет вызывать ошибку компиляции при использовании любого стандартного компилятора. Это фактически сводит практическую ценность такого решения к нулю.
D> Создает более серьезные проблемы, попробуйте: D>
D>is_array<int[]>::value
D>
Этот код не "создает более серьезные проблемы". Этот код просто создает проблемы, ибо никаких других проблем пока обнаружено не было. Эта проблема (опять же глюк MSVC++, ибо внутренне он считает, что 'int[]' — это массив нулевого размера) легко исправляется так:
Здравствуйте, Denn, Вы писали:
D>Здравствуйте, Andrew S, Вы писали:
AS>>Т.е. если размер типа не равен оному после пропуска через такую функцию — это якобы массив. AS>>А если sizeof(T[]) == sizeof(T*) ? AS>>Например, char * и char[4].
D> В общем, теперь, я признаюсь, мне разонравилась идея сравнивания посредством размеров. Слишком, геморрой развивает.
Никакого геммороя она не развивает. Не надо просто пользоваться какими-то странными случайно придуманными типами. Техника давно уже отработана — использовать для обозначения разных результатов ссылки на массивы из 'char' разного размера. Различие размеров в этом случае гарантировано. Более того, конкретные значения размеров в этом случае гарантированы.
D>Особенно, если типы-параметры можно просто сравнить. Например, так:
D>
Опять завязка на эксклюзивную багофичу MSVC++. В стандартном С++ запрещатеся выполнять явную специализацию вложенного класса без специализации внешнего.
D> Надо работать на том, что в случае массива возникает различие!!!
Тоже, как уже говорилось, эксклюзивная багофича MSVC++.
Пойми, что задача состоит не в поиске нестандартных эксклюзивных решений для MSVC++, а в поиске стандартных С++ решений, которые работают и на MSVC++ в том числе.
ME>Понятно, что Метод основан на стандартном неявном преобразовании массива к указателю. ME>А как быть с этим: <... использование типов, с определенным пользователем приведением к указателю ...>
А для этого можно воспользоваться тем фактом, что определенные пользователем приведения типов используются только один раз, а встроенные — многократно. Т.е. достаточно заставить компилятор выполнять на одно преобразование больше, чем нужно, и будут работать только встроенные преобразования:
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, MaximE, Вы писали:
ПК> ME>>Понятно, что Метод основан на стандартном неявном преобразовании массива к указателю. ME>>А как быть с этим: <... использование типов, с определенным пользователем приведением к указателю ...>
ПК>А для этого можно воспользоваться тем фактом, что определенные пользователем приведения типов используются только один раз, а встроенные — многократно. Т.е. достаточно заставить компилятор выполнять на одно преобразование больше, чем нужно, и будут работать только встроенные преобразования:
Ладно, VC6.0 побороли, а что теперь делать с борландом? 5-й вылетает с internal compiler error, 6-й ругается вот так:
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
isarr.cpp:
Error E2034 isarr.cpp 25: Cannot convert 'Crafty1' to 'PointerShim' in function main()
Error E2340 isarr.cpp 25: Type mismatch in parameter 1 (wanted 'PointerShim', got 'Crafty1') in function main()
Error E2285 isarr.cpp 16: Could not find a match for 'is_array_<Crafty1>::is<U_>(Crafty1 *)' in function main()
Error E2109 isarr.cpp 16: Not an allowed type in function main()
Error E2034 isarr.cpp 25: Cannot convert 'Crafty2' to 'PointerShim' in function main()
Error E2340 isarr.cpp 25: Type mismatch in parameter 1 (wanted 'PointerShim', got 'Crafty2') in function main()
Error E2285 isarr.cpp 16: Could not find a match for 'is_array_<Crafty2>::is<U_>(Crafty2 *)' in function main()
Error E2109 isarr.cpp 16: Not an allowed type in function main()
Error E2034 isarr.cpp 25: Cannot convert 'Crafty3' to 'PointerShim' in function main()
Error E2340 isarr.cpp 25: Type mismatch in parameter 1 (wanted 'PointerShim', got 'Crafty3') in function main()
Error E2285 isarr.cpp 16: Could not find a match for 'is_array_<Crafty3>::is<U_>(Crafty3 *)' in function main()
Error E2109 isarr.cpp 16: Not an allowed type in function main()
Error E2285 isarr.cpp 16: Could not find a match for 'is_array_<Crafty1[2]>::is<U_>(Crafty1 ( *)[2])' in function main()
Error E2109 isarr.cpp 16: Not an allowed type in function main()
*** 14 errors in Compile ***
Здравствуйте, Павел Кузнецов, Вы писали:
ПК> ME>>Понятно, что Метод основан на стандартном неявном преобразовании массива к указателю. ME>>А как быть с этим: <... использование типов, с определенным пользователем приведением к указателю ...>
ПК>А для этого можно воспользоваться тем фактом, что определенные пользователем приведения типов используются только один раз, а встроенные — многократно. Т.е. достаточно заставить компилятор выполнять на одно преобразование больше, чем нужно, и будут работать только встроенные преобразования:
ПК>
Как все уже, наверное, поняли, приведенный мною изначальный вариант "распознавателя массивов" на самом деле распознает не именно массивы, а типы, неявно приводимые к типу "указатель", но при этом сами указателями не являющиеся. Массивы являются лишь одним из примеров таких типов. Также в эту группу входят функциональные типы и пользовательские типы с переопределенным оператором приведения типа. Павел в своем сообщении успешно отсеял последние. Но вот функциональные типы по-прежнему проскальзывают сквозь слишком широкую дыру: