【问题标题】:For each type, call a template function with each of these types对于每种类型,使用每种类型调用模板函数
【发布时间】:2021-04-08 22:48:09
【问题描述】:

正如标题所说,我正在尝试创建一些要使用的东西:

template <typename T>
void testFunc(int& i)
{
    ...
}
int i { 0 };
ForEach<int, float>::run<testFunc>(i);

我已经尝试了一些东西,但我遇到了一些问题:

template<typename CurrentComponentType, typename... ComponentTypes>
struct ForEach
{
    template<void (&func)(auto&&... args)>
    static constexpr void run(auto&&... args)
    {
        func<CurrentComponentType>(std::forward<decltype(args)>(args)...);
        ForEach<ComponentTypes...>::run<func>(std::forward<decltype(args)>(args)...);
    }
};

template<typename CurrentComponentType>
struct ForEach<CurrentComponentType>
{
    template<void (&func)(auto&&... args)>
    static constexpr void run(auto&&... args)
    {
        func<CurrentComponentType>(std::forward<decltype(args)>(args)...);
    }
};
  1. 我不知道如何将模板函数作为(模板但不一定)参数。

  2. 由于某些我不明白的原因,我无法再次调用run() 函数:run&lt;func&gt;(。上面写着'&lt;unresolved overloaded function type&gt;'

我认为有很多事情我不明白。

我该如何解决它,为什么它不能以这种方式工作?我误会了什么?

【问题讨论】:

  • testFunc 不是函数,它是模板函数,但run() 的模板参数是函数而不是模板函数。
  • @PatrickRoberts 确实解释了第二个问题......但我不知道如何解决它......
  • 在 C++20 中你可以做到this,你可以用 lambdas 代替模板函数吗?
  • @PatrickRoberts 我是,我只是不知道有什么区别
  • 一个 lambda(即使带有模板参数)是一个值,而模板函数是一个模板值。 C++ 不支持非类型模板模板参数。

标签: c++ template-meta-programming


【解决方案1】:

以下每个解决方案都可以这样使用:

int main(void)
{
    int i { 0 };
    ForEach<int, float>::run<testFunc>(i);
}

因为you can't pass an uninstantiated template function as a (template) parameter,你需要把它做成一个带有operator()的模板类:

#include <utility>

template<typename T>
struct testFunc
{
    void operator()(int& i) {}
};

template<typename T, typename... Ts>
struct ForEach
{
    template<template<typename> typename F, typename... Args>
    static constexpr void run(Args&&... args)
    {
        ForEach<T>::template run<F>(std::forward<Args>(args)...);
        ForEach<Ts...>::template run<F>(std::forward<Args>(args)...);
    }
};

template<typename T>
struct ForEach<T>
{
    template<template<typename> typename F, typename... Args>
    static constexpr void run(Args&&... args)
    {
        F<T>{}(std::forward<Args>(args)...);
    }
};

从C++17开始,可以使用fold expressions来避免递归:

#include <utility>

template<typename T>
struct testFunc
{
    void operator()(int& i) {}
};

template<typename... Ts>
struct ForEach
{
    template<template<typename> typename F, typename... Args>
    static constexpr void run(Args&&... args)
    {
        (F<Ts>{}(std::forward<Args>(args)...), ...);
    }
};

最后,在 C++20 中,您还可以选择使用 lambda with a template parameter list 代替:

#include <utility>

auto testFunc = []<typename T>(int& i) {};

template<typename... Ts>
struct ForEach
{
    template<auto F, typename... Args>
    static constexpr void run(Args&&... args)
    {
        (F.template operator()<Ts>(std::forward<Args>(args)...), ...);
    }
};

【讨论】:

    猜你喜欢
    • 2023-04-02
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多