【问题标题】:Call functor from variadic template从可变参数模板调用函子
【发布时间】:2013-12-27 07:41:56
【问题描述】:

是否可以写一个可变参数模板类

template<typename Functor, int... D>
struct Foo
{
    void bar()
    {
        // ???
    }
};

相当于

template<typename Functor, int D0>
struct Foo<Functor, D0>
{
    void bar()
    {
        Functor f;
        double d0[D0];
        f(d0);
    }
};

template<typename Functor, int D0, int D1>
struct Foo<Functor, D0, D1>
{
    void bar()
    {
        Functor f;
        double d0[D0];
        double d1[D1];
        f(d0, d1);
    }
};

// And so on...

也就是说,传递给函子的参数数量等于模板参数的数量。参数应该在堆栈上分配。

【问题讨论】:

    标签: c++ c++11 variadic-templates


    【解决方案1】:

    通过std::tuple 跟踪带有堆栈参数的版本:

    // Helper class to be able to use expansion of std::get<Index>(tuple)
    template <int... Is> struct index_sequence {};
    
    // Following create index_sequence<0, 1, 2, .., sizeof...(Is) - 1>
    template <int Index, int... Is>
    struct make_index_sequence { // recursively build a sequence of indices
        typedef typename make_index_sequence<Index - 1, Index -1, Is...>::type type;
    };
    
    template <int... Is>
    struct make_index_sequence<0, Is...> { // stop the recursion when 0 is reached
        typedef index_sequence<Is...> type;
    };
    
    template<typename Functor, int... Ds>
    struct Foo
    {
        void bar()
        {
            bar(typename make_index_sequence<sizeof...(Ds)>::type());
        }
    private:
        template <int... Is>
        void bar(index_sequence<Is...>)
        {
            Functor f;
            std::tuple<double[Ds]...> t; // std::tuple<doudle[D0], double[D1], ..>
            f(std::get<Is>(t)...);       // f(std::get<0>(t), std::get<1>(t), ..);
        }
    };
    

    【讨论】:

    • 一个非常好的实现。
    • 您使用的技术推断类型并使用在get&lt;&gt; 中推断为Indices 的类型数对吗?你能解释一下吗?我很难理解indices 扩展。如果您可以发布带有解释的编辑,那就太好了。非常感谢:-)
    • 索引扩展是一种对std::tuple进行迭代的技术。你可以看看stackoverflow.com/questions/16387354/…。
    • 哦,天哪,因为有一点误读,我花了很多时间来理解你的代码(零专业化代码)。误读是struct indices&lt;0, Indices...&gt; { typedef indices&lt;Indices...&gt; type;} 部分,我没有意识到你没有在indices&lt;Indices&gt; 上调用::type,这让我回避到indices&lt;&gt;(导致错误)。我在踢自己:-)
    • 有趣的技术。谢谢!
    【解决方案2】:

    这是你想要的吗?

    template<typename Functor, int... D>
    struct Foo
    {
        template<std::size_t N>
        std::array<double, N> create()
        {
           return std::array<double, N>();
        }
    
        void bar()
        {
           Functor f;
           f(create<D>()...);
        }
    };
    

    【讨论】:

    • 干净简单的解决方案恕我直言。但是 OP 要求的事情略有不同,除了解包到函子之外,他还想要每个数组的本地副本。
    【解决方案3】:

    也许这行得通:

    template <typename Functor, int i, int... others>
    struct Foo
    {
      template <typename ...T>
      void bar(T ... rest)
      {
        double d[i];
        Foo<Functor, others...> foo;
        foo.bar(rest..., d);
      }
    };
    
    template <typename Functor, int i>
    struct Foo<Functor, i>
    {
      template <typename ...T>
      void bar(T ... rest)
      {
        double d[i];
        Functor f;
        f(d, rest...);
      }
    };
    

    【讨论】:

    • @Jarod42 是的,也许。但是你能不能评论一下为什么不呢?
    • 我误读了您的解决方案...请注意,您的 bar 签名与 OP 不同。您可以使用无关参数调用它。
    • @Jarod42 它是不同的,但如果这是一个问题,你可以将其重命名为其他名称并从 bar() 调用它我猜
    猜你喜欢
    • 2012-04-15
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多