Это лучший способ сделать оператор «с» в C ++? - PullRequest
4 голосов
/ 29 октября 2010

Изменить:

Так что этот вопрос был неверно истолкован до такой нелепости, что больше не имеет смысла. Я не знаю, как , поскольку вопрос, который я на самом деле задал , был: моя конкретная реализация этого - да, известно, что это бессмысленно, да, нет отдаленно напоминающий идиоматический макрос C ++ & mdash; был настолько хорош, насколько это возможно, и должен ли он обязательно использовать auto, или вместо этого был подходящий обходной путь. Предполагалось, что это не привлечет столько внимания, и, конечно, не будет неправильного понимания такого масштаба. Бессмысленно просить респондентов редактировать свои ответы, я не хочу, чтобы кто-то терял репутацию из-за этого, и здесь есть некоторая полезная информация для потенциальных будущих зрителей, поэтому я собираюсь произвольно выбрать одного из проголосовавших с меньшим количеством голосов ответы равномерно распределить вовлеченную репутацию. Двигайся, здесь ничего не видно.


Я видел этот вопрос и решил, что было бы интересно написать оператор with на C ++. Ключевое слово auto делает это действительно простым, но есть ли лучший способ сделать это, возможно, без использования auto? Я упустил некоторые фрагменты кода для краткости.

template<class T>
struct with_helper {

    with_helper(T& v) : value(v), alive(true) {}

    T* operator->() { return &value; }
    T& operator*() { return value; }

    T& value;
    bool alive;

};


template<class T> struct with_helper<const T> { ... };


template<class T> with_helper<T>       make_with_helper(T& value) { ... }
template<class T> with_helper<const T> make_with_helper(const T& value) { ... }


#define with(value) \
for (auto o = make_with_helper(value); o.alive; o.alive = false)

Вот (обновленный) пример использования с более типичным случаем, который показывает использование with в том виде, как оно встречается в других языках.

int main(int argc, char** argv) {

    Object object;

    with (object) {

        o->member = 0;
        o->method(1);
        o->method(2);
        o->method(3);

    }

    with (object.get_property("foo").perform_task(1, 2, 3).result()) {

        std::cout
            << (*o)[0] << '\n'
            << (*o)[1] << '\n'
            << (*o)[2] << '\n';

    }

    return 0;

}

Я выбрал o, потому что это необычный идентификатор, а его форма создает впечатление "универсальной вещи". Если у вас есть идея для лучшего идентификатора или более удобного синтаксиса, тогда, пожалуйста, предложите его.

Ответы [ 4 ]

7 голосов
/ 30 октября 2010

Если вы используете auto, зачем вообще использовать макросы?

int main()
{
    std::vector<int> vector_with_uncommonly_long_identifier;

    {
        auto& o = vector_with_uncommonly_long_identifier;

        o.push_back(1);
        o.push_back(2);
        o.push_back(3);
    }

    const std::vector<int> constant_duplicate_of_vector_with_uncommonly_long_identifier
        (vector_with_uncommonly_long_identifier);

    {
        const auto& o = constant_duplicate_of_vector_with_uncommonly_long_identifier;

        std::cout
            << o[0] << '\n'
            << o[1] << '\n'
            << o[2] << '\n';
    }

    {
        auto o = constant_duplicate_of_vector_with_uncommonly_long_identifier.size();
        std::cout << o <<'\n';
    }
}

РЕДАКТИРОВАТЬ: без auto, просто используйте typedef и ссылки.

int main()
{
    typedef std::vector<int> Vec;

    Vec vector_with_uncommonly_long_identifier;

    {
        Vec& o = vector_with_uncommonly_long_identifier;

        o.push_back(1);
        o.push_back(2);
        o.push_back(3);
    }
}
6 голосов
/ 30 октября 2010

?? попытка синтаксиса VB в C ++

with говорит, что все вещи в следующем блоке по умолчанию ссылаются на объект, который я сказал, чтобы сделать это правильно? Выполняет серию операторов с повторными ссылками на один объект или структуру.

with(a)
 .do
 .domore
 .doitall

так как пример дает вам тот же синтаксис?

мне примеры того, почему использовать с, где множественные ссылки

так, а не

book.sheet.table.col(a).row(2).setColour
book.sheet.table.col(a).row(2).setFont
book.sheet.table.col(a).row(2).setText
book.sheet.table.col(a).row(2).setBorder

у вас есть

with( book.sheet.table.col(a).row(2) )
  .setColour
  .setFont
  .setText
  .setBorder

кажется таким же простым и более распространенным синтаксисом в C ++ для

cell& c = book.sheet.table.col(a).row(2);
c.setColour
c.setFont
c.setText
c.setBorder
3 голосов
/ 30 октября 2010

Для C ++ 0x (что вы и предполагаете):

int main() {

    std::vector<int> vector_with_uncommonly_long_identifier;

    {
        auto& o = vector_with_uncommonly_long_identifier;

        o.push_back(1);
        o.push_back(2);
        o.push_back(3);

    }
}
0 голосов
/ 30 октября 2010

Почему бы просто не использовать хорошую лямбду?

auto func = [&](std::vector<int>& o) {
};
func(vector_with_a_truly_ridiculously_long_identifier);

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

...