Моя ситуация
У меня есть два класса, предоставляемых внешним библиотекой, не находящейся под моим контролем, например, их интерфейс для меня фиксирован.
Первый - это шаблонный 2-D контейнер тип, который позволяет мне манипулировать содержимым, хранящимся как в функциях-членах, так и через необработанный указатель. Второй - это класс, содержащий набор функций-членов stati c, которые абстрагируют некоторые сильно оптимизированные для SIMD векторные операции. Большинство из них перегружены, чтобы принимать разные типы данных, однако все они используют один и тот же интерфейс, например
VecOperations::op (Type* dest, const Type* src, /* a variable number of operation specific arguments */, int len)
Чего я хочу достичь:
Я хочу перебрать первое измерение моего 2D контейнер и применить векторную операцию к каждому вектору во второй итерации на месте. Поэтому я хочу заменить, например,
auto** ptrs = conatiner.getArrayOfRawPointers();
for (int i = 0; i < container.getXDim(); ++i)
VecOperations::foo (ptrs[i], ptrs[i], arg1, arg2, arg3, container.getYDim());
в идеале на что-то вроде этого (псевдокод)
forAllElements<VecOperations::foo> (container, arg1, arg2, arg3);
Это должно работать для всех типов типов, хранящихся в моем контейнере, которые поддерживаются вектором классы операций, а также для всех чисел векторных операций указываются c аргументы. Насколько мне известно, написать что-то вроде forAllElements
выше невозможно.
Мое текущее решение:
Вместо этого я придумал:
template <typename ElemType, typename ...Args>
struct ForAllElemements
{
template <void(*op)(ElemType*, const ElemType*, Args..., int)>
static void call (Container<ElemType>& buffer, Args... args)
{
auto xDim = container.getXDim();
auto yDim = container.getYDim();
auto** ptrs = conatiner.getArrayOfRawPointers();
for (int i = 0; i < xDim; ++i)
op (ptrs[i], const_cast<const ElemType*>(ptrs[i]), args..., yDim);
}
};
Это можно использовать как
// using a Container<float> and VecOperations::foo (float*, const float*, float, int, float, int)
ForAllElemements<float, float, int, float>::call<VecOperations::foo> (container, arg1, arg2, arg3);
Хотя в C ++ 17 вывод аргументов шаблона класса из конструктора работает, вывод его из вызова функции stati c не работает, насколько мне известно. Насколько я понимаю, это просто не определено, технически я не вижу причин, по которым
ForAllElemements::call<VecOperations::foo> (container, arg1, arg2, arg3);
должно быть невозможно, поскольку все типы шаблонов могут быть выведены из параметров, передаваемых в функцию stati c. .
Итак, я спрашиваю вас, есть ли какой-нибудь очень умный обходной путь или шаблон, о котором я не знаю, который сделал бы что-то подобное с C ++ 17 или с более поздними стандартами?