代码之家  ›  专栏  ›  技术社区  ›  Thomas Eding

你能在通话地点交错可变参数吗?

  •  4
  • Thomas Eding  · 技术社区  · 4 年前

    是否可以在函数调用站点内部交错模板参数?

    我实际上想实现以下内容,但不知道如何实现(psuedo代码):

    template <size_t... indices, typename... Ts>
    void foo(const Things *things)
    {
        static_assert(sizeof...(indices) == sizeof...(Ts));
        constexpr n = sizeof...(Ts);
        bar(
          indices[0], parse<Ts[0]>(things[0]),
          indices[1], parse<Ts[1]>(things[1]),
          ...
          indices[n-1], parse<Ts[n-1]>(things[n-1]));
    }
    

    注意:我知道可以完成以下操作(psuedo代码):

    template <size_t... indices, typename... Ts>
    void foo(const Things *things)
    {
        static_assert(sizeof...(indices) == sizeof...(Ts));
        constexpr n = sizeof...(Ts);
        bar(
          indices[0], indices[1], ..., indices[n-1],
          parse<Ts[0]>(things[0]),
          parse<Ts[1]>(things[1]),
          ...
          parse<Ts[n-1]>(things[n-1]));
    }
    

    我提出的部分解决方案是添加一个swizzling组件:

    template <typename Func>
    decltype(auto) swizzle()
    {
        return Func();
    }
    
    template <typename Func, typename T0>
    decltype(auto) swizzle(size_t i0, T0 &&t0)
    {
        return Func(i0, std::forward<T0>(t0));
    }
    
    template <typename Func, typename T0, typename T1>
    decltype(auto) swizzle(size_t i0, size_t i1, T0 &&t0, T1 &&t1)
    {
        return Func(i0, std::forward<T0>(t0), i1, std::forward<T1>(t1));
    }
    

    但我想我必须手动编写每种情况下的每一个我想考虑的情况。

    1 回复  |  直到 4 年前
        1
  •  3
  •   Patrick Roberts Benjamin Gruenbaum    4 年前

    这样地:

    template <size_t... indices, typename... Ts>
    void foo(const Things *things)
    {
        std::apply([](auto...args) {
            bar(args...);
        }, std::tuple_cat(std::make_tuple(indices, parse<Ts>(*(things++)))...));
    }
    

    如果 bar 是lambda而不是函数模板,您只需传递 酒吧 直接作为 std::apply .

    如果要避免复制的返回值 parse<Ts>(*(things++)) ,你可以使用 std::forward_as_tuple 而不是 std::make_tuple .

    如果 *(things++) 让你不舒服的是使用 std::index_sequence :

    template <size_t... indices, typename... Ts>
    void foo(const Things *things)
    {
        [=]<auto... Is>(std::index_sequence<Is...>) {
            std::apply([](auto...args) {
                bar(args...);
            }, std::tuple_cat(std::make_tuple(indices, parse<Ts>(things[Is]))...));
        }(std::index_sequence_for<Ts...>());
    }