#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 …