【问题标题】:Call a variadic template functor in a variadic template parameter pack if it satisfies a condition如果满足条件,则在可变参数模板参数包中调用可变参数模板函子
【发布时间】:2021-05-06 13:14:24
【问题描述】:

我有一个可变参数模板仿函数类:

template <typename Result, typename... Arguments>
class Functor
{
public:
    using FunctionType = std::function<Result(Arguments...)>;
    Result operator() (const Arguments&... arguments) { return Function(arguments); }
    std::string GetName() { return Name; }
    Functor(const std::string& name, const FunctionType& function) : Name(name), Function(function) { }
private:
    std::string Name;
    FunctionType Function;
}

还有一个可变参数模板函数:

template <typename... Functors>
void Function(const Functors&... functors) { }

假设我已经声明了一些Functors 并想在Function 中使用它们:

Functor<int, int> f
(
    "f",
    [](int x) -> int { return 2 * x - 1; }
);
Functor<int, int, int> g
(
    "g",
    [](int x, int y) -> int { return x + 2 * y - 3; }
);
Function(f, g);

Function内部,我想找出参数包中传递给它的Functor满足某个条件,如果满足,调用函子。像下面的伪代码:

template <typename... Functors>
void Function(const Functors&... functors)
{
    foreach (Functor functor in functors)
    {
        if (functor.GetName() == "f")
        {
            functor(); // the functor can have different parameter lists so this is another problem
        }
    }
}

我想知道是否有办法做到这一点。我还想知道,由于Functors 可以有不同的参数列表,即使我能够找到正确的Functor 来调用它们,我该如何调用它们?假设有一个std::vector&lt;int&gt;,当Functor 以三个ints 作为参数时,是否可以将前三个ints 传递给Functor

【问题讨论】:

    标签: c++ variadic-templates variadic-functions functor variadic


    【解决方案1】:

    在 C++17 中,这很容易使用 fold expressions 解决。

    #include <functional>
    #include <string>
    
    template <typename Result, typename... Arguments>
    class Functor
    {
    public:
        using FunctionType = std::function<Result(Arguments...)>;
        Result operator() (const Arguments&... args) {
            return this->Function(arguments...);
        }
        std::string GetName() {
            return this->Name;
        }
        Functor(const std::string& name, const FunctionType& function)
            : Name(name), Function(function) { }
    
    private:
        std::string Name;
        FunctionType Function;
    };
    
    template <typename... Functors>
    void ForEachFunctor(const Functors&... functors)
    {
        ((functors.getName() == "f" && functors()), ...);
    }
    

    在这里,我们利用&amp;&amp; 运算符的短路。只有当条件functors.getName() == "f" 为真时,才会计算运算符的右侧。

    稍微不那么老套的方法使用单独的函数:

    template <typename Functor>
    void InvokeIfNamedF(const Functor &functor) {
        if (functor.GetName() == "f")
            functor();
    }
    
    template <typename... Functors>
    void ForEachFunctor(const Functors&... functors)
    {
        (InvokeIfNamedF(functors), ...);
    }
    

    参数包的元素使用逗号操作符组合。然而,在这个例子中,我们调用了每个没有参数的函子。如果所有仿函数都有不同的签名,那么将它们作为一个包传递并有条件地一次调用它们可能是不可能的。

    【讨论】:

      猜你喜欢
      • 2021-10-01
      • 2016-12-01
      • 1970-01-01
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 2013-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多