Страницы

Поиск по вопросам

воскресенье, 15 марта 2020 г.

Ограничение области видимости мелких функций

#cpp #namespace


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

Интересует, что думают об этих вариантах профессиональные программисты и, возможно,
ещё что-то посоветуют?

// вариант №1 отдельное пространство имен, где собирается весь утилитарный хлам
namespace makemove { 
    template 
        inline void SWAP(T & a, T & b) noexcept {
            T t = a;
            a = b;
            b = t;
        }
}

void board15::makemove(const directions & dir) {
    using namespace makemove;
//#define SWAP(a,b) {int t = (a); (a) = (b); (b) = t;} // вариант № 2
    switch (dir) {
        case UP:
            // там внутри не самые короткие выражения, нет смысла их приводить
            SWAP(board[/* ... */], board[/* ... */]); 
            current_pos_y += 1;
            break;

        case DOWN:
            SWAP(board[/* ... */], board[/* ... */]);
            current_pos_y -= 1;
            break;

        case LEFT:
            SWAP(board[/* ... */], board[/* ... */]);
            current_pos_x += 1;
            break;

        case RIGHT:
            SWAP(board[/* ... */], board[/* ... */]);
            current_pos_x -= 1;
            break;
    }
//#undef SWAP
    return;
}


P.S. в std::swap из "utility" тыкать не надо, это к вопросу не относится.
    


Ответы

Ответ 1



Если вам где-нибудь нужна мелкая функция, чтобы не засорять область видимости, можно положить её в анонимное пространство имён: namespace { template inline void SWAP(T & a, T & b) noexcept { T t = a; a = b; b = t; } } Таким образом функция будет видна только в том файле, где определена, и не будет вызывать конфликтов компоновщика, если в соседнем файле объявлена такая же. Эта техника имеет смысл при использовании в .cpp-файлах, при использовании в header'ах вы, наоборот, получаете много копий одинакового кода.

Ответ 2



Я - не профессиональный программист, так как я - всего лишь безработный, но тем не менее выскажу свое мнение.:) Если эта общая часть кода дублируется в нескольких функциях - членах класса board15, то я выделил бы его в отдельную приватную функцию этого же класса. Функция может быть либо статической, либо не статической в зависимости от того, нужно ли ей иметь дело с другими нестатическими членами класса помимо тех, которые можно ей передать в виде аргументов. Например, class board15 { private: static void swap( Board &board1, Board &board2 ) { // можно ее определить внутри класса, чтобы сделать ее встраиваемой // либо просто добавить спецификатор функции inline в ее объявление // если это целесообразно. } //... }; То есть если эта функция входит в реализацию вашего класса и не является обобщенной для нескольких классов или объектов, то ее следует сделать членом вашего классе. Это не мешает ей быть к тому же шаблонной функцией. Что касается данного подхода namespace makemove { template inline void SWAP(T & a, T & b) noexcept { T t = a; a = b; b = t; } } void board15::makemove(const directions & dir) { using namespace makemove; //... То я бы его сходу забраковал. Непонятно, почему классы, которые используют функцию и сама функция объявлены в различных пространствах имен, если эта функция связана с объектами только этих классов. И вместо using директивы я рекомендовал бы по крайней мере использовать using объявление данной функции.

Ответ 3



Можно пометить функцию ключевым словом static, чтобы она была видна только в текущем файле. Ну и естественно, её не надо включать в заголовочный файл с прототипами.

Комментариев нет:

Отправить комментарий