[英]How can I pass a function template as (template) argument to a function template?
Currently, I have a code like目前,我有一个代码
#include <cstdint>
#include <iostream>
template<std::uint32_t idx>
void f() {
std::cout << "f(" << idx << ")\n";
}
template<std::uint32_t n>
void loop1() {
f<n>();
if constexpr (n > 0) {
loop1<n - 1>();
}
}
template<std::uint32_t idx>
void g() {
std::cout << "g(" << idx << ")\n";
}
template<std::uint32_t n>
void loop2() {
g<n>();
if constexpr (n > 0) {
loop2<n - 1>();
}
}
int main() {
loop1<4>();
loop2<2>();
}
It's necessary for f
, g
, loop1
and loop2
to be function templates. f
、 g
、 loop1
和loop2
必须是 function 模板。 Now, I have to add more functions, but loop1
and loop2
will always be the same, a recursive template loop.现在,我必须添加更多功能,但loop1
和loop2
将始终相同,一个递归模板循环。
How can I pass the function template as (template) argument to loop
to achieve something like:我如何将 function 模板作为(模板)参数传递给loop
以实现类似的目的:
#include <cstdint>
#include <iostream>
template<std::uint32_t idx>
void f() {
std::cout << "f(" << idx << ")\n";
}
template<std::uint32_t idx>
void g() {
std::cout << "g(" << idx << ")\n";
}
template<std::uint32_t n, typename h>
void loop() {
h<n>();
if constexpr (n > 0) {
loop<n - 1, h>();
}
}
int main() {
loop<4, h>();
loop<2, h>();
}
I prefer to pass the function as template argument at compile time, but a solution to pass the function template as function argument at runtime would also solve my problem, eg我更喜欢在编译时将 function 作为模板参数传递,但是在运行时将 function 模板作为 function 参数传递的解决方案也可以解决我的问题,例如
#include <cstdint>
#include <iostream>
template<std::uint32_t idx>
void f() {
std::cout << "f(" << idx << ")\n";
}
template<std::uint32_t idx>
void g() {
std::cout << "g(" << idx << ")\n";
}
template<std::uint32_t n, typename T>
void loop(T h) {
h<n>();
if constexpr (n > 0) {
loop<n - 1>(h);
}
}
int main() {
loop<4>(h);
loop<2>(h);
}
or要么
#include <cstdint>
#include <iostream>
template<std::uint32_t idx>
void f() {
std::cout << "f(" << idx << ")\n";
}
template<std::uint32_t idx>
void g() {
std::cout << "g(" << idx << ")\n";
}
template<std::uint32_t n, template<std::uint32_t> typename F>
void loop(F h) {
h<n>();
if constexpr (n > 0) {
loop<n - 1>(h);
}
}
int main() {
loop<4>(h);
loop<2>(h);
}
Is this even possible?这可能吗? I know, that all of my approaches are wrong syntax.我知道,我所有的方法都是错误的语法。 It's just to illustrate, what I want to achieve.这只是为了说明,我想要实现的目标。
You cannot do this with free functions but you can do something similar to what you want to have with class template static member functions:您不能使用自由函数执行此操作,但您可以使用 class 模板 static 成员函数执行类似于您想要的操作:
#include <cstdint>
#include <iostream>
template<std::uint32_t idx>
struct F {
static void function() {
std::cout << "f(" << idx << ")\n";
}
};
template<std::uint32_t idx>
struct G {
static void function() {
std::cout << "g(" << idx << ")\n";
}
};
template<std::uint32_t n, template<std::uint32_t> typename T>
void loop() {
T<n>::function();
if constexpr (n > 0) {
loop<n - 1, T>();
}
}
int main() {
loop<4, F>();
loop<2, G>();
}
For this I would recommend a either a generic or a template lambda. The goal of our solution would be to send in a predicate that can receive the parameter idx
at compile time.为此,我会推荐一个通用的或模板 lambda。我们的解决方案的目标是发送一个可以在编译时接收参数idx
的谓词。
With template lambda (C++20):使用模板 lambda (C++20):
#include <cstdint>
#include <iostream>
template<std::uint32_t idx>
void f() {
std::cout << "f(" << idx << ")\n";
}
template<std::uint32_t idx>
void g() {
std::cout << "g(" << idx << ")\n";
}
template<std::uint32_t n, typename F>
void loop(F h) {
h.template operator()<n>();
if constexpr (n > 0) {
loop<n - 1>(h);
}
}
int main() {
loop<4>([]<std::uint32_t idx>() {
return f<idx>();
});
loop<2>([]<std::uint32_t idx>() {
return g<idx>();
});
}
This is the closest solution to what you posted.这是与您发布的内容最接近的解决方案。 The lambda there is a type with a templated operator()
. lambda 有一个带有模板化operator()
的类型。
With generic lambda (compatible with C++14)使用通用 lambda(与 C++14 兼容)
#include <cstdint>
#include <iostream>
template<std::uint32_t idx>
void f() {
std::cout << "f(" << idx << ")\n";
}
template<std::uint32_t idx>
void g() {
std::cout << "g(" << idx << ")\n";
}
template<std::uint32_t n, typename F>
void loop(F h) {
h(std::integral_constant<std::uint32_t, n>{});
if constexpr (n > 0) {
loop<n - 1>(h);
}
}
int main() {
loop<4>([](auto idx) {
return f<idx>();
});
loop<2>([](auto idx) {
return g<idx>();
});
}
This solution is using generic lambdas, but is still a templated lambda in reality.此解决方案使用通用 lambda,但实际上仍然是模板化的 lambda。 idx
is taking the type of std::integral_constant
which can be sent as template parameter since its conversion operator to std::uint32_t
is constexpr. idx
采用可以作为模板参数发送的std::integral_constant
类型,因为它到std::uint32_t
的转换运算符是 constexpr。
I would replace the template functions f
and g
by structs F
and G
respectively, each one with a template method invoke
:我将分别用结构F
和G
替换模板函数f
和g
,每个函数都有一个模板方法invoke
:
struct F {
template<std::uint32_t idx>
void invoke() {
std::cout << "f(" << idx << ")\n";
}
};
struct G {
template<std::uint32_t idx>
void invoke() {
std::cout << "g(" << idx << ")\n";
}
};
template<std::uint32_t n, typename F>
void loop(F h) {
h.template invoke<n>();
if constexpr (n > 0) {
loop<n - 1>(h);
}
}
Nothing stops you from adding template functions f
and g
that call invoke
for F
and G
respectively:没有什么能阻止您添加分别为F
和G
调用invoke
的模板函数f
和g
:
template<std::uint32_t idx>
void f() {
F().invoke<idx>();
}
template<std::uint32_t idx>
void g() {
G().invoke<idx>();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.