Ну, есть способы, но они требуют больше строк, чем ваша текущая реализация. И я не уверен, что следующая реализация улучшит читаемость больше, чем просто помещение вашего «нечистого» раздела в отдельную функцию.
Следующий код, вероятно, длиннее, чем он будет для вас, потому что я реализовал два способа (непосредственный вызов и получение указателя на функцию) и два примера, чтобы показать, что это действительно работает.
#include <iostream>
#include <string>
template <bool pred0, bool pred1, bool pred2, bool pred3, bool pred4>
void Func1()
{
std::cout << "func1: " << pred0 << pred1 << pred2 << pred3 << pred4 << std::endl;
}
template <bool pred0, bool pred1, bool pred2, bool pred3, bool pred4>
struct Func1Wrapper
{
static constexpr auto Ptr = Func1<pred0, pred1, pred2, pred3, pred4>;
static void Call()
{
Func1<pred0, pred1, pred2, pred3, pred4>();
}
};
template <bool pred0, bool pred1, bool pred2>
void Func2()
{
std::cout << "func2: " << pred0 << pred1 << pred2 << std::endl;
}
template <bool pred0, bool pred1, bool pred2>
struct Func2Wrapper
{
static constexpr auto Ptr = Func2<pred0, pred1, pred2>;
static void Call()
{
Func2<pred0, pred1, pred2>();
}
};
template <template<bool...> class F, bool... preds>
struct Ct
{
template <bool newPred>
using Expanded = Ct<F, preds..., newPred>;
static void CallFunc()
{
F<preds...>::Call();
}
static auto GetFunc()
{
return F<preds...>::Ptr;
}
};
template <class DeducedPreds, typename BoolLast>
void Rt2Ct(BoolLast predLast)
{
if (predLast)
DeducedPreds::template Expanded<true>::CallFunc();
else
DeducedPreds::template Expanded<false>::CallFunc();
}
template <class DeducedPreds, typename BoolFirst, typename ...BoolRest>
void Rt2Ct(BoolFirst predFirst, BoolRest... predRest)
{
if (predFirst)
Rt2Ct<typename DeducedPreds::template Expanded<true>, BoolRest...>(predRest...);
else
Rt2Ct<typename DeducedPreds::template Expanded<false>, BoolRest...>(predRest...);
}
template <template<bool...> class F, typename ...Bools>
void FuncCaller(Bools... preds)
{
Rt2Ct<Ct<F>, Bools...>(preds...);
}
template <class DeducedPreds, typename BoolLast>
auto Rt2CtGet(BoolLast predLast)
{
if (predLast)
return DeducedPreds::template Expanded<true>::GetFunc();
else
return DeducedPreds::template Expanded<false>::GetFunc();
}
template <class DeducedPreds, typename BoolFirst, typename ...BoolRest>
auto Rt2CtGet(BoolFirst predFirst, BoolRest... predRest)
{
if (predFirst)
return Rt2CtGet<typename DeducedPreds::template Expanded<true>, BoolRest...>(predRest...);
else
return Rt2CtGet<typename DeducedPreds::template Expanded<false>, BoolRest...>(predRest...);
}
template <template<bool...> class F, typename ...Bools>
auto FuncGetter(Bools... preds)
{
return Rt2CtGet<Ct<F>, Bools...>(preds...);
}
int main(int argc, char* argv[])
{
FuncCaller<Func1Wrapper>(std::stoi(argv[1]), std::stoi(argv[2]), std::stoi(argv[3]), std::stoi(argv[4]), std::stoi(argv[5]));
auto f2 = FuncGetter<Func2Wrapper>(std::stoi(argv[1]), std::stoi(argv[3]), std::stoi(argv[5]));
f2();
return 0;
}
Код требует C++14 (C++11 должен быть возможен с небольшим переписыванием) и свободен от CUDA, потому что я действительно не вижу, как вызов ядра вместо обычной функции меняет проблему. Конечно, вам придется добавить несколько параметров для передачи dimGrid
и dimBlock
, а также всех необходимых args
.
Как уже отмечалось, вы можете поместить if-else
за пределы цикла for
. Вот почему я также реализовал подпрограмму FuncGetter
.
Также обратите внимание, что вы можете убедиться, что аргументы шаблона Bools
, BoolFirst
и т. д. действительно относятся к типу bool
.
Компиляция, вызов функции и вывод:
$ g++ -std=c++14 main.cpp && ./a.out 1 0 1 0 0
func1: 10100
func2: 110
person
BlameTheBits
schedule
07.11.2020
foo
делает одно из двух. Вы можете закрыть это с помощью oneif/else
. Но таким образом у вас естьif/else
внутриfoo
и 4 условий для выбора правильного шаблона. Так... оно того стоит? Кроме того, да,predAll = pred1 && pred2
совершенно избыточен и сбивает с толку. - person churill   schedule 06.11.2020foo
значительно сложнее.pred
и друзья предоставляют ярлыки через пару уровней ветвления внутри ядра, большинство из которых вызывает различные функции устройства, все из которых также принимаютpred
и друзей в качестве параметров шаблона. - person Jacob Faib   schedule 06.11.2020if-else
в коде рабочего хоста должна быть инкапсулирована в отдельную функцию, но в остальном у вас уже есть чистый подход. - person JaMiT   schedule 06.11.2020true/false x true/false
) до 2 + 2. - person 463035818_is_not_a_number   schedule 06.11.2020foo
) запускает очень жесткий цикл с привязкой к памяти. Аргументы шаблона гарантируют ядрам (если они истинны), что данные кратны некоторому числу и, следовательно, правильно выровнены в памяти для векторизованных загрузок/сохранений. Без аргументов шаблона ядрам пришлось бы вычислять на лету дорогостоящие переменные по модулю. - person Jacob Faib   schedule 06.11.2020