Компактифицировать синтаксис вызова функций C ++ - PullRequest
0 голосов
/ 08 января 2019

Я хотел бы уменьшить количество синтаксиса, необходимого для ссылки на функцию, и мне было интересно, есть ли способ сделать что-то вроде:

(НЕ СОБИРАЕТСЯ)

using pushToLastUsed = mSomeLongStackFIFOObject.push_back;
// or
auto pushToLastUsed = mSomeLongStackFIFOObject.push_back;

тогда я мог бы что-то вроде:

pushToLastUsed(10);

вместо:

mSomeLongStackFIFOObject.push_back(10);

Конечно, я мог бы сделать макрос вроде:

#define pushToLastUsed mSomeLongStackFIFOObject.push_back

// some code using it here

#undef pushToLastUsed

но я бы предпочел не использовать макросы.

Ответы [ 4 ]

0 голосов
/ 09 января 2019

Вы можете достичь желаемого поведения, связав объект mSomeLongStackFIFOObject с функцией-членом push_back и используя заполнитель для его аргумента. Для этого требуется как минимум компилятор C ++ 11.

Рассмотрим следующий пример:

#include <functional>
#include <iostream>

struct A {
  void push_back(const int& n) { std::cout << "push_back(" << n << ")\n"; }
};

int main() {
  A mSomeLongStackFIFOObject;

  std::function<void(const int&)> pushToLastUsed = std::bind(
    &A::push_back,
    &mSomeLongStackFIFOObject,
    std::placeholders::_1
  );

  pushToLastUsed(10);  // push_back(10)
}

Некоторые примечания по этому поводу:

  1. Как уже правильно сказал Мирко, вызов нестатической функции-члена в основном аналогичен вызову статической функции-члена с this в качестве неявного первого параметра. Привязка экземпляра struct A в качестве первого параметра использует этот факт.
  2. Вывод типа с использованием auto работает для функций-членов без каких-либо параметров, но не в вышеуказанном случае.
  3. Если нестатическая функция-член перегружена (например, std::vector<T>::push_back), необходимо явно указать параметры шаблона для шаблона функции std::bind. Смотрите Использование std :: tr1 :: bind с std :: vector :: push_back или Есть ли проблемы с boost :: bind с VS2010? для получения дополнительной информации.
0 голосов
/ 08 января 2019

Моей первой идеей было что-то вроде другого ответа. При повторном прочтении вашего вопроса я понимаю, что в основном вам нужно избегать повторения длинного имени объекта. Скрытие вызова стандартной функции должно быть сделано с осторожностью, поскольку его основной эффект - запутывание вашего кода. Все знают, что делает push_back, но даже вы, вероятно, забудете, что именно делает pushToLastUse. Другим вариантом является псевдоним только mSomeLongStackFIFOObject с более коротким именем, как в

auto& short_name = mSomeLongStackFIFIObject;
short_name.push_back(10);
0 голосов
/ 08 января 2019

Когда вы пишете mSomeLongStackFIFOObject.push_back(10); вы на самом деле звоните SomeLongStackFIFOClass::push_back(&mSomeLongStackFIFOObject, 10);

Один из вариантов сделать:

auto& m= mSomeLongStackFIFOObject;

А потом:

m.push_back(10);

Это сократит его и позволит вам использовать любую переменную, которая вам нравится.

Если переменная глобальная, вы всегда можете сделать:

static inline void pushBack(int n) { mSomeLongStackFIFOObject.push_back(n); }

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

0 голосов
/ 08 января 2019

Одним из решений может быть использование лямбда-выражения для записи вызова функции в вызываемый объект:

#include <vector>

void foo(std::vector<int> & bar)
{
    auto pushToLastUsed = [&bar](int index) {
        bar.push_back(index);
    };

    pushToLastUsed(10);
}

Хотя, на мой взгляд, от этого очень мало пользы, даже если вы замените bar очень длинным идентификатором.

...