Функциональный макрос и перечислитель с одинаковым именем - PullRequest
3 голосов
/ 14 марта 2019

В следующем фрагменте у меня есть struct IndexError, что я вернуться, когда пользователь сделал ошибку, используя мою библиотеку. У меня есть функциональный макрос, который приводит указатель на IndexError*, и enum, оба с именем INDEX_ERROR.

enum errors {
    SUCCESS,
    INVALID_ARGUMENT,
    INDEX_ERROR
};

struct Error {
    char error_buff[BUFSIZ];
};

typedef struct Error Error;

struct IndexError {
    Error  parent;
    size_t invalid_index;
    // etc.
};

typedef struct IndexError IndexError;


#define INDEX_ERROR(obj) ((IndexError*) obj)

Пример того, как я мог бы использовать это:

size_t pos = 4;
int IndexPointer* error = NULL;
int status = array_remove_item(my_array, pos, &error);

Тогда я проверяю статус. Если он не вернет SUCCESS, я бы изучил ошибку, потому что это должно указывать на вновь созданную ошибку.

Реализация одной из функций массива может выглядеть следующим образом:

int array_remove_item(Array* array, size_t pos, Error** error_out)
{
    Error* error = NULL;
    if(pos >= array->size) {
        index_error_create(INDEX_ERROR(&error), pos); // use casting macro.
        *error_out = error;
        return INDEX_ERROR; // is this the macro or the value from the errors enum?
    }
    priv_array_remove_item(array, pos);
    return SUCCESS;
}

Так что мой вопрос в return INDEX_ERROR;, вернет ли INDEX_ERROR значение из перечисления, или препроцессор укусит меня, потому что мое именование неудобно?

1 Ответ

7 голосов
/ 14 марта 2019
return INDEX_ERROR; // is this the macro or the value from the errors enum?

Это перечислитель.Это не может быть результатом расширения функционально-подобного макроса, потому что за ним сразу не следует левый токен (, так как препроцессору требуется 1 .

Этохотя немного вонючий.Различные имена для макроса и перечислителя сделают код более понятным и самоочевидным без необходимости читать мелкий шрифт спецификации языка.


1 - n1570 6.10.3p10 "Каждый последующий экземпляр функционально-подобного имени макроса сопровождается символом (в качестве следующего токена предварительной обработки вводится последовательность токенов предварительной обработки, которая заменяется списком замены в определении"

...