Как я могу сохранить ‘first’ и ‘second’, заменив std::pair на struct?

#c #struct #std-pair

#c #структура #std-pair

Вопрос:

У меня есть пара std::pair<int, long> , и в коде в разных местах используются pr.first pr.second (также ppr->first ppr->second ) обозначения. Теперь я хочу изменить пару на struct,

 struct ABC 
{
    int a;
    long b;
};
 

есть ли способ сохранить эти ‘first’ и ‘second’ обозначения в коде для доступа к этой структуре? Может быть, создание функции?

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

1. У вас могут быть просто открытые члены first и second в вашей структуре?

2. Но я не могу назвать их первыми и вторыми из-за проблем с удобочитаемостью кода

3. Способ, которым это std::pair работает, заключается в том, что он вызывает свои члены first и second ; это не специальный синтаксис.

Ответ №1:

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

 struct ABC
{
    int first;
    long second;
};
 

Но если вы хотите, чтобы члены назывались как-то по-другому, и вы не хотите прибегать к функциям «getter» (для которых потребуются круглые скобки на вызывающем сайте), решением является использование ссылок для переменных-членов:

 struct ABC {
    int a;
    long b;

    intamp; first;
    longamp; second;

    ABC() : first(a), second(b) {}
};
 

Но если вы примете это, вам нужно будет самостоятельно написать конструкторы, которые являются частью «правила 5», чтобы правильно связать ссылки, иначе, казалось бы, обезболивающее копирование или перемещение не будет работать.

Хотя этот ответ демонстрирует мощь C , язык славится своей способностью позволять вам стрелять себе в ногу. Каким бы фантастическим ни было решение, вероятность появления любопытных ошибок по мере развития вашей кодовой базы и даже самого языка невозможно переоценить. Таким образом, это следует рассматривать как антипаттерн и использовать только в действительно исключительных обстоятельствах.

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

1. В общем случае вы не можете повторно привязать ссылку. В частности, если ваш оператор присваивания говорит (например) a = other.a , то автоматически first также примет новое значение. Единственный раз, когда вам когда-либо понадобится повторно связать ссылку, это если вы попытаетесь memcpy использовать тип.

2. @Resurrection: лучшее, что можно сделать прямо сейчас, это оставить std::pair все как есть.

3. @Bathsheba полностью согласен. 🙂

4. Я могу понять утверждение о «правиле 5» . Недавно у меня был неудачный опыт (когда я использовал что-то подобное в своем производительном коде). Когда я создал шаблон конструктора копирования, внезапно конструктор копирования по умолчанию был сгенерирован неявно (о чем я не знал) и сделал плохие вещи. 😉

5. @Scheff: Я разделяю такие же плохие воспоминания!

Ответ №2:

Возможно, вы захотите попробовать это:

 struct ABC 
{
    union {
        int a;
        int first;
    };
    union {
        long b;
        long second;
    };
};
 

Это позволяет вам использовать a и first , а также b second взаимозаменяемы.
Возможно, было бы лучше заменить first и second обычаи, чтобы избежать путаницы.

Как указывалось, это неопределенное поведение 12.3 Unions , но оно будет работать, по крайней мере, с MSVC и GCC. спасибо за комментарии

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

1. Доступ к членам объединения, отличным от используемых для инициализации, является неопределенным поведением .

2. Технически это UB в C (хотя он определен в C). Хотя я думаю, что большинство компиляторов C скомпилируют это, особенно те, которые якобы «поддерживают» C (например, MSVC). Если вы адекватно откажетесь, я проголосую против, поскольку это гениальное решение.

3. Следует отметить, что документы gcc разрешают ввод типов через объединения даже с -fstrict-aliasing помощью on . Но он явно не документирует его как расширение C …