Каковы наилучшие методы достижения стирания типов в современном C++?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Каковы наилучшие методы достижения стирания типов в современном C++?

Сообщение Anonymous »

Пример
Рассмотрим следующий фрагмент:
int main(){
std::vector a{-2, -1, 0, 1, 2};
std::vector b{-0.2, -0.1, 0., 0.1, 2.};
std::vector c{0, 1, 2, 3, 4, 5};
// number of vectors can scale to 20+

auto n = a.size();

if (b.size() != n) throw std::runtime_error("vector size mismatch");
if (c.size() != n) throw std::runtime_error("vector size mismatch");
// ...

// might also contain other checks

a.clear();
b.clear();
c.clear();
d.clear();
// ...
}

Этот код много повторений и плохо масштабируется при большом количестве векторов.
Вопрос
Как лучше всего (с точки зрения читаемости и удобства сопровождения) избежать этого повторения в данном примере с современным C++?
Пытаясь найти решение, я понял, что существует несколько возможных способов решения этой проблемы. Во всех решениях используются разные функции C++, которые взяты из разных стандартов C++ и требуют разного уровня понимания новых функций C++. Поэтому мне становится трудно понять, что уже считается старой школой, что можно считать современной, а что можно считать постмодернистской практикой C++. Чего можно ожидать от опытного программиста, если он не ограничен каким-либо стандартом C++?
Некоторые решения SO устарели (8+ лет), что очень затрудняет понимание их актуальности для современного C++. А ответы ChatGPT не дают понимания, насколько распространено решение и считается ли оно лучшей практикой.
Разные подходы, которые я видел
Наверное, есть и другие решения. Буду признателен за ответы в образовательных целях.
std::vector стирание типов с помощью void* (C++03)
std::vector vec_ptrs;
vec_ptrs.push_back(&a);
vec_ptrs.push_back(&b);
vec_ptrs.push_back(&c);

for (auto* p : vec_ptrs) {
if (static_cast(p)->size() != n)
throw std::runtime_error("size mismatch")), ...);
}

for (auto* p : vec_ptrs) {
static_cast(p)->clear();
}


Стирание типов операций с помощью std::function (C++11)
// To me it is a half solution, as it abstracts the operations, but still requires 2xN lines of code
std::vector size_op = {
[&]{ return a.size(); },
[&]{ return b.size(); },
[&]{ return c.size(); },
};

std::vector clear_ops = {
[&]{ a.clear(); },
[&]{ b.clear(); },
[&]{ c.clear(); },
};

for (auto& size_op : size_ops)
if (size_op() != n) throw std::runtime_error("vector size mismatch");

for (auto& clear_op : clear_ops)
clear_op();

std::tie с помощью std::apply (C++17)
auto vecs = std::tie(a, b, c);

std::apply([&](auto&... v) {
((v.size() == n ? void() : throw std::runtime_error("size mismatch")), ...);
}, vecs);

std::apply([](auto&... v) { (v.clear(), ...); }, vecs);

Шаблон лямбды (C++20)
auto vecs = std::tie(a, b, c);

auto check_sizes = [n](const Vecs&... vs) {
((vs.size() == n ? void() : throw std::runtime_error("size mismatch")), ...);
};

std::apply([](auto&... v) { (v.clear(), ...); }, vecs);



Подробнее здесь: https://stackoverflow.com/questions/798 ... n-modern-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»