C/C++: Вызывание функции без споров с функцией, которая ничего не возвращает

Почему не возможно вызывать функцию, которая не берет споров с вызовом функции как аргумент, который не возвращает значения (который, по моему скромному мнению, эквивалентен вызыванию функции, которая не берет аргументов без аргументов).

Например:

void foo(void) {...}
void bar(void) {...}

foo(bar())

Не понимайте меня превратно, я знаю void не значение и что его нельзя рассматривать как одно.

С моей логикой это имело бы смысл, и должно быть возможно сделать это. Я имею в виду, почему нет? Какой-либо аргумент, почему это не должно быть возможно?

14
задан Null 6 July 2015 в 16:34
поделиться

9 ответов

Я не убежден, что любая из причин, по которым я слышал, являются хорошими.

См., В C ++ вы можете вернуть результат функции :

void foo() {
    // ...
}

void bar() {
    // ...
    return foo();
}

Да, это точно так же, как:

foo();
return;

, но гораздо более соответствует общему программированию, чтобы вы могли сделать Функция экспедиции работает без необходимости беспокоиться о том, является ли управляемая функция , void .

Итак, если аналогичная система применяется так, что A пустота возврата представляла собой нулевый вызов в сценарии композиции функции, которые могли бы сделать композицию функции более универсальными.

8
ответ дан 1 December 2019 в 13:59
поделиться

Поскольку, согласно пункту 3.9.1 / 9 стандарта,

Экспрессия типа Void должна использоваться только как оператор выражения (6.2), как операнда выражения запятой (5.18), как второй или третий операнд из?: (5.16), как операнд Тип, или как выражение в Отчет о возврате (6.6.3) для Функция с типом возврата пустота.

C / C ++ просто не предназначен, чтобы быть таким универсальным. Вы DO Get Получите Возврат returns_void (); Для оптимизации Call-Call, это функционально-ish, верно? : vp

Редактировать: Вышеуказанное правило все равно позволит вам вызвать Take_Void (3) с 3 , преобразованным в void . Это запрещено на 8,3,5 / 2:

, если параметр-объявление-предложение - это пусто, функция не принимает нет аргументы. Список параметров (пустота) эквивалентно пустую параметр список. За исключением этого спецназа, void не должен быть типом параметра (Хотя типы, полученные из пустоты, такие как пустота *, может).

3
ответ дан 1 December 2019 в 13:59
поделиться

На данный момент у меня есть что-то подобное в моем коде: #define Eval (f) f (++ Evavsounter) Не спрашивайте меня, почему я его использую, я просто должен. Обычно F не принимает никаких ценностей. Я только что добавил этот (глобальный) целое число, чтобы что-то подсчитать. Разве это не будет намного лучше, если бы у меня было что-то вроде #define Eval (f) f (Bummy (++ EvalCounter))?

Вы пробовали оператор запятой:

#define EVAL(f)   (++evalcounter, f())
0
ответ дан 1 December 2019 в 13:59
поделиться

Давайте притворяться, что это работает. Можете ли вы подумать о одном гипотетическом случае, где

bar();
foo();

, который имеет именно то же самое, не значительно более читаемое и разумное?

отредактировано. Да, да. :)

0
ответ дан 1 December 2019 в 13:59
поделиться

Я добавлю одно дополнительное заявление: void baz(int);

Теперь очевидно, что если аргумент с типом void равен никаким аргументам, то два аргумента, один из которых имеет тип void, будут равны одному аргументу (так как 0 = 1*x <=> 1 = 1+1*x)

Таким образом, очевидно, что это законно: baz(1, bar());. Но также (так как void - это "ничего") baz(bar(),1);.

И мы можем продолжить в этом смысле: baz(bar(), 1, bar());. В конце концов, "void is nothing".

Либо вы запрещаете его прямо, накладываете произвольные ограничения, либо в итоге разрешаете нелепые конструкции. Я согласен с выбором первого разрешения

.
0
ответ дан 1 December 2019 в 13:59
поделиться

Любое отрицательное нечетное число не работает. Однако, чтобы ответить на ваш вопрос, если вы знаете, что у вас могут быть отрицательные числа, просто делите на 2. Это превращается в сдвиг с фиксацией jit/компилятором.

-121--3763297-

Двоеточия играют особую роль в URL-адресах - например, для обозначения порта и поэтому «зарезервированы» ( см. здесь ).

URL-адреса используют некоторые символы для специальных используется при определении синтаксиса. Когда эти символы не используются в своих специальная роль внутри URL, они должны для кодирования

Таким образом, двоеточие должно быть удалено.

-121--4407546-

Поскольку void не позволяет указать имя аргумента, которое требуется для получения возвращаемого значения первой функции, независимо от того, что она фактически возвратила.

0
ответ дан 1 December 2019 в 13:59
поделиться

Это делает своего рода смысл ( бар ничего не производит, Foo ничего не потребляет, поэтому FO (BAR ()) должен быть допущен). ОТО, это было бы только спутать читателя. Если вы хотите быть L33T, всегда есть , , , и || операторы для эмуляции запятых.

1
ответ дан 1 December 2019 в 13:59
поделиться

Не существует документировано здесь :

Исключение «Не существует» наследует от django.core.exceptions. ObjectDoesNotExist, таким образом, вы можете нацеливаться на несколько Исключения DousNotExist.

, поэтому вы можете использовать , кроме ObjectDousNotExist: , и ловить все исключения DousNotExist , которые могут возникнуть в предложении try , или использовать , кроме SomeSpecificModel.DousNotExist: , если вы хотите быть более конкретными.

Если вы ищете конкретное место в исходном коде Джанго, где этот атрибут добавляется к классам моделей, см. здесь , строки 34-37:

# Create the class.
new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')})
new_class.add_to_class('_meta', Options(attrs.pop('Meta', None)))
new_class.add_to_class('DoesNotExist', types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}))
-121--1210728-

LLVM предоставляет много, но это все еще лишь небольшая часть времени выполнения, необходимого функциональному языку. Вызовы C FFI являются несложными, поскольку LLVM оставляет управление памятью для обработки кем-то другим. Взаимодействие с сборщиком мусора затрудняет вызовы FFI на таких языках, как Scheme.

Возможно, вас интересует HLVM , но на данный момент это не просто эксперимент.

-121--1227218-

Если список параметров (void) был обработан одинаково со всеми другими параметрами перечислять в C/C + +, семантическим значением, если такое объявление параметра будет «один параметр типа void ». Если бы это было так, вполне возможно, что для целей единообразия язык позволял бы «связывать» вызовы к таким функциям, как показано в вашем примере. (По крайней мере, C++, вероятно, будет, поскольку он допускает такой вид однородности в операторах return ).

Однако в языке C++, а также в языке C список параметров, имеющий вид (void) , не обрабатывается равномерно с другими формами списков параметров. Вместо этого он имеет особое значение. Это означает, что функция не имеет параметров вообще . (Эквивалентно пустым () в C++).

Другими словами, функция, объявленная списком параметров (void) , принимает параметры ноль . Вы поставляете один . Это то, что делает это незаконным. Учитывая особое значение списка параметров (void) в C/C + +, разрешение

foo(bar());

не будет сильно отличаться от разрешения

foo(bar(), bar());
foo(bar(), bar(), bar());

. Качественно 2 и 3 так же сильно отличаются от 0, как и 1.

2
ответ дан 1 December 2019 в 13:59
поделиться

LLVM обеспечивает много возможностей, но это все еще лишь небольшая часть времени выполнения, необходимого функциональному языку. Вызовы C FFI являются несложными, поскольку LLVM оставляет управление памятью для обработки кем-то другим. Взаимодействие с сборщиком мусора затрудняет вызовы FFI на таких языках, как Scheme.

Возможно, вас интересует HLVM , но на данный момент это не просто эксперимент.

-121--1227218-

(Слегка упрощено) Есть два человека, завинчивающих гайки на болты.

Процедура (одинаковая для обоих):

  1. Поднимите гайку или болт
  2. Поднимите болт или гайку (в зависимости от того, что у вас еще нет)
  3. Вверните гайку на болт
  4. Поместите готовую сборку в «готовую» кучу.
  5. если гайки и болты остаются, переходите к шагу 1

Так что происходит, когда остается только гайка и болт? Первое лицо берет гайку, второе захватывает болт. Пока что хорошо, но сейчас они застряли, у каждого есть ресурс, который нужен другому.

Без специальных инструкций они будут сидеть там в тупике вечно.

Или вы можете просто показать им это видео

-121--1367522-

Не вводите в заблуждение с помощью обозначения. Скорее раздражает то, что С использует прототип f (void) для обозначения « f ожидает отсутствие параметров», а не « f ожидает единственный параметр типа void ». Обозначение f () было сохранено для обозначения «количество параметров, которое ожидает f , неизвестно, поэтому вы можете называть его с любым количеством параметров, которые вам нравятся, и удачи вам». До ANSI Standard C (он же C89) не было такой вещи, как прототип функции, и вам нужен был инструмент, такой как lint , чтобы защитить вас от даже самых обыденных видов ошибок с параметрами, таких как передача неверного количества параметров или передача параметра с дико несовместимым типом.

Что касается того, почему нельзя использовать значение функции, возвращающей void в качестве значения, или почему нельзя передать параметр функции, которая не ожидает параметров, то эти ограничения применяются для защиты от самых обычных видов ошибок с параметрами.

2
ответ дан 1 December 2019 в 13:59
поделиться