Можно ли как-то заменить макрос
У меня в коде часто встречается ситуация, что к одной и той же переменной нужно обращаться много-много раз.
Предположим, что есть структура
struct S{
std::vector<size_t> vector_in_s;
};
И еще одна, которая хранит первую
struct V{
std::vector<S> vector_in_v;
};
Теперь я начинаю это как-то использовать
int main(){
V str_v;
str_v.vector_in_v[12].vector_in_s[7] = 0; // A
str_v.vector_in_v[11].vector_in_s[3] = 9; // B
str_v.vector_in_v[88].vector_in_s[8] = 3; // C
// auto& A = str_v.vector_in_v[12].vector_in_s[7];
// auto& B = str_v.vector_in_v[11].vector_in_s[3];
// auto& C = str_v.vector_in_v[88].vector_in_s[8];
// Так я сделать не могу, потому что, когда я добавляю что-то в вектор, он может
// перевыделить память и все ссылки становятся недействительными
// Приходится каждый раз прописывать полностью, потому что я не могу объявить три ссылки
if (str_v.vector_in_v[12].vector_in_s[7] != str_v.vector_in_v[11].vector_in_s[3]){
str_v.vector_in_v[12].vector_in_s[7].emplace_back(33);
str_v.vector_in_v[11].vector_in_s[3].emplace_back(2);
}
}
Я нашел решение - макрос
#define A str_v.vector_in_v[12].vector_in_s[7]
#define B str_v.vector_in_v[11].vector_in_s[3]
#define C str_v.vector_in_v[88].vector_in_s[8]
Тогда код принимает вид
int main(){
V str_v;
#define A str_v.vector_in_v[12].vector_in_s[7]
#define B str_v.vector_in_v[11].vector_in_s[3]
#define C str_v.vector_in_v[88].vector_in_s[8]
if (A != B){
A.emplace_back(33);
B.emplace_back(2);
}
#undef A
#undef B
#undef C
}
Но мне не нравится такая практика; хочется избавиться от макросов и заменить это 'чем-нибудь'
Ответы (4 шт):
Раз ссылка не подходит, тогда лямбда.
auto foo = [&]() -> auto & {return str_v.vector_in_v[12].vector_in_s[7];};
foo().emplace_back(42);
а почему бы не написать функцию
int get(int index_v, int index_s)
{
return str_v.vector_in_v[index_v].vector_in_s[index_s]
}
upd
struct S{
std::vector<size_t> vector_in_s;
size_t operator()(int index) { return vector_in_s[index]; }
};
struct V{
std::vector<S> vector_in_v;
S operator()(int index) { return vector_in_v[index]; }
};
V str_v;
str_v(12)(7).emplace_back(42);
// Правильность не гарантирую, но смысл вот такой
Вам точно надо именно
struct S{
std::vector<size_t> vector_in_s;
};
struct V{
std::vector<S> vector_in_v;
};
а не
vector<vector<size_t>> v;
И все ваши обращения тогда вырождаются в выражения вроде
v[5][10] = 7;
Зачем именно структуры?
Это можно сделать посредством создания объекта-запроса, инкапсулирующего обращение по индексу. Такой подход также позволит в перспективе добавить удобные методы для реализации дополнительных операций, например для обращения к соседним элементам и т.п.
class
t_Query final
{
private: ::std::size_t m_outer_index;
private: ::std::size_t m_inner_index;
public: explicit constexpr
t_Query(::std::size_t const outer_index, ::std::size_t const inner_index) noexcept
: m_outer_index{outer_index}
, m_inner_index{inner_index}
{
return;
}
public: auto &
operator [](V & container) const noexcept
{
return container.vector_in_v[m_outer_index].vector_in_s[m_inner_index];
}
public: auto const &
operator [](V const & container) const noexcept
{
return container.vector_in_v[m_outer_index].vector_in_s[m_inner_index];
}
};
int main()
{
V str_v;
constexpr t_Query const loca{12, 7};
constexpr t_Query const locb{11, 3};
// ...
loca[str_v] = 3;
locb[str_v] = 9;
if (loca[str_v] != locb[str_v])
{
// ...
}
return 0;
}