Пространства имен в C

Неустранимая ошибка: не может использовать возвращаемое значение функции в контексте записи

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

Пример:

if (empty(is_null(null))) {
  echo 'empty';
}

Это связано с тем, что empty - это языковая конструкция, а не функция, она не может быть вызвана с выражением в качестве аргумента в версиях PHP до 5.5. До PHP 5.5 аргумент empty() должен быть переменной , но произвольное выражение (такое как возвращаемое значение функции) допустимо в PHP 5.5 +.

empty, несмотря на его имя, на самом деле не проверяет, является ли переменная «пустой». Вместо этого он проверяет, существует ли переменная, или == false. Выражения (например, is_null(null) в примере) всегда будут считаться существующими, поэтому здесь empty проверяет только, равен ли он false. Здесь вы можете заменить empty() на !, например. if (!is_null(null)), или явно сравнить с ложным, например. if (is_null(null) == false).

Вопросы, относящиеся

51
задан Brian Tompsett - 汤莱恩 3 February 2016 в 05:30
поделиться

3 ответа

При использовании префиксов пространства имен я обычно добавляю макросы для сокращенных имен, которые могут быть активированы через #define NAMESPACE_SHORT_NAMES перед включением заголовка. Заголовок foobar.h мог бы быть похожим на это:

// inclusion guard
#ifndef FOOBAR_H_
#define FOOBAR_H_

// long names
void foobar_some_func(int);
void foobar_other_func();

// short names
#ifdef FOOBAR_SHORT_NAMES
#define some_func(...) foobar_some_func(__VA_ARGS__)
#define other_func(...) foobar_other_func(__VA_ARGS__)
#endif

#endif

, Если я хочу использовать краткие названия во включении файла, я сделаю

#define FOOBAR_SHORT_NAMES
#include "foobar.h"

, я нахожу это более чистым и более полезным решением, чем использование макросов пространства имен, как описано Vinko Vrsalovic (в комментариях).

49
ответ дан Christoph 7 November 2019 в 09:45
поделиться

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

// foo.h
#ifndef FOO_H
#define FOO_H
typedef struct { 
  int (* const bar)(int, char *);
  void (* const baz)(void);
} namespace_struct;
extern namespace_struct const foo;
#endif // FOO_H

// foo.c
#include "foo.h"
static int my_bar(int a, char * s) { /* ... */ }
static void my_baz(void) { /* ... */ }
namespace_struct const foo = { my_bar, my_baz }

// main.c
#include <stdio.h>
#include "foo.h"
int main(void) {
  foo.baz();
  printf("%d", foo.bar(3, "hello"));
  return 0;
}

В вышеупомянутом примере, my_bar и my_baz не может быть назван непосредственно от main.c, только до foo.

, Если у Вас есть набор пространств имен, которые объявляют функции с теми же подписями, тогда можно стандартизировать структуру пространства имен для того набора и выбрать который пространство имен использовать во времени выполнения.

// goo.h
#ifndef GOO_H
#define GOO_H
#include "foo.h"
extern namespace_struct const goo;
#endif // GOO_H

// goo.c
#include "goo.h"
static int my_bar(int a, char * s) { /* ... */ }
static void my_baz(void) { /* ... */ }
namespace_struct const goo = { my_bar, my_baz };

// other_main.c
#include <stdio.h>
#include "foo.h"
#include "goo.h"
int main(int argc, char** argv) {
  namespace_struct const * const xoo = (argc > 1 ? foo : goo);
  xoo->baz();
  printf("%d", xoo->bar(3, "hello"));
  return 0;
}

повторные определения my_bar и my_baz не конфликтуют, так как они определяются статически, но базовые функции все еще доступны через соответствующую структуру пространства имен.

82
ответ дан rampion 7 November 2019 в 09:45
поделиться

Вы могли использовать ## оператор:

#define FUN_NAME(namespace,name) namespace ## name

и объявляют функции как:

void FUN_NAME(MyNamespace,HelloWorld)()

довольно неловкие Взгляды все же.

13
ответ дан Mehrdad Afshari 7 November 2019 в 09:45
поделиться