Using fields stored in variadic data structure as method arguments












4















I have a variadic data structure, each "layer" containing one field.



How can use all the fields stored in the structure as arguments to a function or a constructor?



template <class... Ts> class Builder {};

template <class T, class... Ts>
class Builder<T, Ts...> : public Builder<Ts...> {
public:
Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

Result build() {
// want to use tail, Builder<Ts...>::tail, etc.
// as ctor or function arguments without multiple specializations
}

private:
const T tail;
};


In general, I want to be capable of doing something like this:



Builder<int, string, int> b1{10, "aaa", 20};
Result r1 = b1.build(); // should invoke Result's constructor (int, string, int)

Builder<int> b2{10};
Result r2 = b2.build(); // should invoke Result's constructor (int)









share|improve this question




















  • 1





    And why not just hold a std::tuple and use the many standard library utilities to make ones life easier?

    – StoryTeller
    Nov 14 '18 at 14:28











  • The builder is unfortunately only a simplification, in real scenario it's a composite buffer composed of multiple sub-buffers that return the value (the field tail does not exist).

    – Adam Kotwasinski
    Nov 14 '18 at 14:34








  • 2





    The solution utilizes the tail field. So if the example is not indicative, and the solution is not applicable, what was accomplished here?

    – StoryTeller
    Nov 14 '18 at 14:35
















4















I have a variadic data structure, each "layer" containing one field.



How can use all the fields stored in the structure as arguments to a function or a constructor?



template <class... Ts> class Builder {};

template <class T, class... Ts>
class Builder<T, Ts...> : public Builder<Ts...> {
public:
Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

Result build() {
// want to use tail, Builder<Ts...>::tail, etc.
// as ctor or function arguments without multiple specializations
}

private:
const T tail;
};


In general, I want to be capable of doing something like this:



Builder<int, string, int> b1{10, "aaa", 20};
Result r1 = b1.build(); // should invoke Result's constructor (int, string, int)

Builder<int> b2{10};
Result r2 = b2.build(); // should invoke Result's constructor (int)









share|improve this question




















  • 1





    And why not just hold a std::tuple and use the many standard library utilities to make ones life easier?

    – StoryTeller
    Nov 14 '18 at 14:28











  • The builder is unfortunately only a simplification, in real scenario it's a composite buffer composed of multiple sub-buffers that return the value (the field tail does not exist).

    – Adam Kotwasinski
    Nov 14 '18 at 14:34








  • 2





    The solution utilizes the tail field. So if the example is not indicative, and the solution is not applicable, what was accomplished here?

    – StoryTeller
    Nov 14 '18 at 14:35














4












4








4


1






I have a variadic data structure, each "layer" containing one field.



How can use all the fields stored in the structure as arguments to a function or a constructor?



template <class... Ts> class Builder {};

template <class T, class... Ts>
class Builder<T, Ts...> : public Builder<Ts...> {
public:
Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

Result build() {
// want to use tail, Builder<Ts...>::tail, etc.
// as ctor or function arguments without multiple specializations
}

private:
const T tail;
};


In general, I want to be capable of doing something like this:



Builder<int, string, int> b1{10, "aaa", 20};
Result r1 = b1.build(); // should invoke Result's constructor (int, string, int)

Builder<int> b2{10};
Result r2 = b2.build(); // should invoke Result's constructor (int)









share|improve this question
















I have a variadic data structure, each "layer" containing one field.



How can use all the fields stored in the structure as arguments to a function or a constructor?



template <class... Ts> class Builder {};

template <class T, class... Ts>
class Builder<T, Ts...> : public Builder<Ts...> {
public:
Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

Result build() {
// want to use tail, Builder<Ts...>::tail, etc.
// as ctor or function arguments without multiple specializations
}

private:
const T tail;
};


In general, I want to be capable of doing something like this:



Builder<int, string, int> b1{10, "aaa", 20};
Result r1 = b1.build(); // should invoke Result's constructor (int, string, int)

Builder<int> b2{10};
Result r2 = b2.build(); // should invoke Result's constructor (int)






c++ c++11 recursion variadic-templates template-meta-programming






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 14:38









max66

35.5k73964




35.5k73964










asked Nov 14 '18 at 14:25









Adam KotwasinskiAdam Kotwasinski

2,538827




2,538827








  • 1





    And why not just hold a std::tuple and use the many standard library utilities to make ones life easier?

    – StoryTeller
    Nov 14 '18 at 14:28











  • The builder is unfortunately only a simplification, in real scenario it's a composite buffer composed of multiple sub-buffers that return the value (the field tail does not exist).

    – Adam Kotwasinski
    Nov 14 '18 at 14:34








  • 2





    The solution utilizes the tail field. So if the example is not indicative, and the solution is not applicable, what was accomplished here?

    – StoryTeller
    Nov 14 '18 at 14:35














  • 1





    And why not just hold a std::tuple and use the many standard library utilities to make ones life easier?

    – StoryTeller
    Nov 14 '18 at 14:28











  • The builder is unfortunately only a simplification, in real scenario it's a composite buffer composed of multiple sub-buffers that return the value (the field tail does not exist).

    – Adam Kotwasinski
    Nov 14 '18 at 14:34








  • 2





    The solution utilizes the tail field. So if the example is not indicative, and the solution is not applicable, what was accomplished here?

    – StoryTeller
    Nov 14 '18 at 14:35








1




1





And why not just hold a std::tuple and use the many standard library utilities to make ones life easier?

– StoryTeller
Nov 14 '18 at 14:28





And why not just hold a std::tuple and use the many standard library utilities to make ones life easier?

– StoryTeller
Nov 14 '18 at 14:28













The builder is unfortunately only a simplification, in real scenario it's a composite buffer composed of multiple sub-buffers that return the value (the field tail does not exist).

– Adam Kotwasinski
Nov 14 '18 at 14:34







The builder is unfortunately only a simplification, in real scenario it's a composite buffer composed of multiple sub-buffers that return the value (the field tail does not exist).

– Adam Kotwasinski
Nov 14 '18 at 14:34






2




2





The solution utilizes the tail field. So if the example is not indicative, and the solution is not applicable, what was accomplished here?

– StoryTeller
Nov 14 '18 at 14:35





The solution utilizes the tail field. So if the example is not indicative, and the solution is not applicable, what was accomplished here?

– StoryTeller
Nov 14 '18 at 14:35












5 Answers
5






active

oldest

votes


















2














If you don't want to use tuple as a member to hold the values, you could do it this way:



template <class... Ts> class Builder {
protected:
template<class...Us>
Result do_build(const Us&...us){
return Result(us...);
}
};

template <class T, class... Ts>
class Builder<T, Ts...> : public Builder<Ts...> {
public:
Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

Result build() {
return do_build();
}
protected:
template<class...Us>
Result do_build(const Us&...us){
return Builder<Ts...>::do_build(us...,tail);
}
private:
const T tail;
};





share|improve this answer
























  • How would build() work? Can you elaborate?

    – rustyx
    Nov 14 '18 at 20:26











  • @rustyx this way action: godbolt.org/z/DCT3L6

    – Oliv
    Nov 14 '18 at 20:43



















1














template <class... Ts>struct Builder {
auto as_tie() const { return std::tie(); }
};

template <class T, class... Ts>
struct Builder<T, Ts...> : Builder<Ts...> {
using base = Builder<Ts...>;
auto as_tie()const{
return std::tuple_cat( base::as_tie(), std::tie( tail ) );
}


now Builder::as_tie() can be passed to std::apply (or backported version) or make_from_tuple.



Naturally the operator T trick can be used for return type deduction. But I'd usually advise against it.






share|improve this answer































    1














    You can use an Idx<n> tag to get tail from n-th Builder:



    template<std::size_t i> struct Idx {};

    template<class... Ts>
    class Builder {
    public:
    void get_tail();
    };

    template <class T, class... Ts>
    class Builder<T, Ts...> : public Builder<Ts...> {
    private:
    static constexpr auto index = sizeof...(Ts);

    public:
    Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {
    }

    Result build() {
    return build_impl(std::make_index_sequence<index + 1>{});
    }

    protected:
    using Builder<Ts...>::get_tail;

    const T& get_tail(Idx<index>) {
    return tail;
    }

    private:
    template<std::size_t... is>
    Result build_impl(std::index_sequence<is...>) {
    return Result{get_tail(Idx<index - is>{})...};
    }

    private:
    const T tail;
    };





    share|improve this answer

































      1














      I suppose you can use a lambda (and save it in a std::function) to stock values.



      Something as (caution: code not tested) (thanks to Oliv for a correction)



      template <typename ... Ts>
      class Builder
      {
      private:
      std::function<Result()> fn;

      public:
      Builder (Ts const & ... ts) : fn{ [=]{ return Result{ts...}; }
      { }

      Result build ()
      { return fn(); }
      };





      share|improve this answer





















      • 1





        Should not the ts... be captured? Then all these values are going to be stored on the heap, that is really expensive for such a small functionality.

        – Oliv
        Nov 14 '18 at 14:47











      • @Oliv - sure: Builder (Ts & ... ts) : fn{ { return Result{ts...}; }; but it's dangerous; if one construct Builder with a value that is destroyed before the build() calling, the corresponding saved reference is a dangling reference. Maybe it's possible to do something with perfect forwarding, but you have to templatize the constructor.

        – max66
        Nov 14 '18 at 15:10








      • 1





        Your code is ill formed you must capture! And in order not to have UB parameters have to be captured by value. [=]

        – Oliv
        Nov 14 '18 at 19:31











      • @Oliv - so, it seems to me, is better to receive arguments as Ts const & ...; maybe, this way, some copy are avoided (but I suspect that the compilers optimize this aspect).

        – max66
        Nov 14 '18 at 20:09



















      1














      One of the solutions I found is to pass intermediary tuple<...> that contains the fields and then unpack it using the mechanism described in "unpacking" a tuple to call a matching function pointer :



      // unpacking helpers
      template<int ...> struct seq {};

      template<int N, int ...S>
      struct gens : gens<N-1, N-1, S...> {};

      template<int ...S>
      struct gens<0, S...> {
      typedef seq<S...> type;
      };

      // Builder with 0 fields returns an empty tuple
      template <class... Ts> class Builder {
      public:
      tuple<> compute_tuple() {
      return {};
      }
      };

      template <class T, class... Ts>
      class Builder<T, Ts...> : public Builder<Ts...> {
      public:
      Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

      Result build() {
      // get argument tuple
      auto arguments = compute_tuple();
      // use argument tuple as Result's argument
      return build_recursively(typename gens<1 + sizeof... (Ts)>::type{}, arguments);
      }

      protected:
      // computing tuple - just join current element with superclass' result
      tuple<T, Ts...> compute_tuple() {
      const tuple<T> head{field};
      const tuple<Ts...> tail = Builder<Ts...>::compute_tuple();
      return tuple_cat(head, tail);
      }

      private:
      template<int ...S>
      Result build_recursively(seq<S...>, tuple<T, Ts...> data) {
      // invoked matching Result's constructor
      return { std::get<S>(data) ... };
      }

      const T field;
      };


      Then it behaves properly:



      Builder<string, string> b1{"a", "b"};
      b1.build(); // invokes Result(string, string)


      Still, maybe it's possible to do something simpler without that tuple intermediary?






      share|improve this answer

























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53302451%2fusing-fields-stored-in-variadic-data-structure-as-method-arguments%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        5 Answers
        5






        active

        oldest

        votes








        5 Answers
        5






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        2














        If you don't want to use tuple as a member to hold the values, you could do it this way:



        template <class... Ts> class Builder {
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Result(us...);
        }
        };

        template <class T, class... Ts>
        class Builder<T, Ts...> : public Builder<Ts...> {
        public:
        Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

        Result build() {
        return do_build();
        }
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Builder<Ts...>::do_build(us...,tail);
        }
        private:
        const T tail;
        };





        share|improve this answer
























        • How would build() work? Can you elaborate?

          – rustyx
          Nov 14 '18 at 20:26











        • @rustyx this way action: godbolt.org/z/DCT3L6

          – Oliv
          Nov 14 '18 at 20:43
















        2














        If you don't want to use tuple as a member to hold the values, you could do it this way:



        template <class... Ts> class Builder {
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Result(us...);
        }
        };

        template <class T, class... Ts>
        class Builder<T, Ts...> : public Builder<Ts...> {
        public:
        Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

        Result build() {
        return do_build();
        }
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Builder<Ts...>::do_build(us...,tail);
        }
        private:
        const T tail;
        };





        share|improve this answer
























        • How would build() work? Can you elaborate?

          – rustyx
          Nov 14 '18 at 20:26











        • @rustyx this way action: godbolt.org/z/DCT3L6

          – Oliv
          Nov 14 '18 at 20:43














        2












        2








        2







        If you don't want to use tuple as a member to hold the values, you could do it this way:



        template <class... Ts> class Builder {
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Result(us...);
        }
        };

        template <class T, class... Ts>
        class Builder<T, Ts...> : public Builder<Ts...> {
        public:
        Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

        Result build() {
        return do_build();
        }
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Builder<Ts...>::do_build(us...,tail);
        }
        private:
        const T tail;
        };





        share|improve this answer













        If you don't want to use tuple as a member to hold the values, you could do it this way:



        template <class... Ts> class Builder {
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Result(us...);
        }
        };

        template <class T, class... Ts>
        class Builder<T, Ts...> : public Builder<Ts...> {
        public:
        Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

        Result build() {
        return do_build();
        }
        protected:
        template<class...Us>
        Result do_build(const Us&...us){
        return Builder<Ts...>::do_build(us...,tail);
        }
        private:
        const T tail;
        };






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 14 '18 at 14:38









        OlivOliv

        9,0491957




        9,0491957













        • How would build() work? Can you elaborate?

          – rustyx
          Nov 14 '18 at 20:26











        • @rustyx this way action: godbolt.org/z/DCT3L6

          – Oliv
          Nov 14 '18 at 20:43



















        • How would build() work? Can you elaborate?

          – rustyx
          Nov 14 '18 at 20:26











        • @rustyx this way action: godbolt.org/z/DCT3L6

          – Oliv
          Nov 14 '18 at 20:43

















        How would build() work? Can you elaborate?

        – rustyx
        Nov 14 '18 at 20:26





        How would build() work? Can you elaborate?

        – rustyx
        Nov 14 '18 at 20:26













        @rustyx this way action: godbolt.org/z/DCT3L6

        – Oliv
        Nov 14 '18 at 20:43





        @rustyx this way action: godbolt.org/z/DCT3L6

        – Oliv
        Nov 14 '18 at 20:43













        1














        template <class... Ts>struct Builder {
        auto as_tie() const { return std::tie(); }
        };

        template <class T, class... Ts>
        struct Builder<T, Ts...> : Builder<Ts...> {
        using base = Builder<Ts...>;
        auto as_tie()const{
        return std::tuple_cat( base::as_tie(), std::tie( tail ) );
        }


        now Builder::as_tie() can be passed to std::apply (or backported version) or make_from_tuple.



        Naturally the operator T trick can be used for return type deduction. But I'd usually advise against it.






        share|improve this answer




























          1














          template <class... Ts>struct Builder {
          auto as_tie() const { return std::tie(); }
          };

          template <class T, class... Ts>
          struct Builder<T, Ts...> : Builder<Ts...> {
          using base = Builder<Ts...>;
          auto as_tie()const{
          return std::tuple_cat( base::as_tie(), std::tie( tail ) );
          }


          now Builder::as_tie() can be passed to std::apply (or backported version) or make_from_tuple.



          Naturally the operator T trick can be used for return type deduction. But I'd usually advise against it.






          share|improve this answer


























            1












            1








            1







            template <class... Ts>struct Builder {
            auto as_tie() const { return std::tie(); }
            };

            template <class T, class... Ts>
            struct Builder<T, Ts...> : Builder<Ts...> {
            using base = Builder<Ts...>;
            auto as_tie()const{
            return std::tuple_cat( base::as_tie(), std::tie( tail ) );
            }


            now Builder::as_tie() can be passed to std::apply (or backported version) or make_from_tuple.



            Naturally the operator T trick can be used for return type deduction. But I'd usually advise against it.






            share|improve this answer













            template <class... Ts>struct Builder {
            auto as_tie() const { return std::tie(); }
            };

            template <class T, class... Ts>
            struct Builder<T, Ts...> : Builder<Ts...> {
            using base = Builder<Ts...>;
            auto as_tie()const{
            return std::tuple_cat( base::as_tie(), std::tie( tail ) );
            }


            now Builder::as_tie() can be passed to std::apply (or backported version) or make_from_tuple.



            Naturally the operator T trick can be used for return type deduction. But I'd usually advise against it.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 14 '18 at 14:49









            Yakk - Adam NevraumontYakk - Adam Nevraumont

            184k19191376




            184k19191376























                1














                You can use an Idx<n> tag to get tail from n-th Builder:



                template<std::size_t i> struct Idx {};

                template<class... Ts>
                class Builder {
                public:
                void get_tail();
                };

                template <class T, class... Ts>
                class Builder<T, Ts...> : public Builder<Ts...> {
                private:
                static constexpr auto index = sizeof...(Ts);

                public:
                Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {
                }

                Result build() {
                return build_impl(std::make_index_sequence<index + 1>{});
                }

                protected:
                using Builder<Ts...>::get_tail;

                const T& get_tail(Idx<index>) {
                return tail;
                }

                private:
                template<std::size_t... is>
                Result build_impl(std::index_sequence<is...>) {
                return Result{get_tail(Idx<index - is>{})...};
                }

                private:
                const T tail;
                };





                share|improve this answer






























                  1














                  You can use an Idx<n> tag to get tail from n-th Builder:



                  template<std::size_t i> struct Idx {};

                  template<class... Ts>
                  class Builder {
                  public:
                  void get_tail();
                  };

                  template <class T, class... Ts>
                  class Builder<T, Ts...> : public Builder<Ts...> {
                  private:
                  static constexpr auto index = sizeof...(Ts);

                  public:
                  Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {
                  }

                  Result build() {
                  return build_impl(std::make_index_sequence<index + 1>{});
                  }

                  protected:
                  using Builder<Ts...>::get_tail;

                  const T& get_tail(Idx<index>) {
                  return tail;
                  }

                  private:
                  template<std::size_t... is>
                  Result build_impl(std::index_sequence<is...>) {
                  return Result{get_tail(Idx<index - is>{})...};
                  }

                  private:
                  const T tail;
                  };





                  share|improve this answer




























                    1












                    1








                    1







                    You can use an Idx<n> tag to get tail from n-th Builder:



                    template<std::size_t i> struct Idx {};

                    template<class... Ts>
                    class Builder {
                    public:
                    void get_tail();
                    };

                    template <class T, class... Ts>
                    class Builder<T, Ts...> : public Builder<Ts...> {
                    private:
                    static constexpr auto index = sizeof...(Ts);

                    public:
                    Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {
                    }

                    Result build() {
                    return build_impl(std::make_index_sequence<index + 1>{});
                    }

                    protected:
                    using Builder<Ts...>::get_tail;

                    const T& get_tail(Idx<index>) {
                    return tail;
                    }

                    private:
                    template<std::size_t... is>
                    Result build_impl(std::index_sequence<is...>) {
                    return Result{get_tail(Idx<index - is>{})...};
                    }

                    private:
                    const T tail;
                    };





                    share|improve this answer















                    You can use an Idx<n> tag to get tail from n-th Builder:



                    template<std::size_t i> struct Idx {};

                    template<class... Ts>
                    class Builder {
                    public:
                    void get_tail();
                    };

                    template <class T, class... Ts>
                    class Builder<T, Ts...> : public Builder<Ts...> {
                    private:
                    static constexpr auto index = sizeof...(Ts);

                    public:
                    Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {
                    }

                    Result build() {
                    return build_impl(std::make_index_sequence<index + 1>{});
                    }

                    protected:
                    using Builder<Ts...>::get_tail;

                    const T& get_tail(Idx<index>) {
                    return tail;
                    }

                    private:
                    template<std::size_t... is>
                    Result build_impl(std::index_sequence<is...>) {
                    return Result{get_tail(Idx<index - is>{})...};
                    }

                    private:
                    const T tail;
                    };






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 14 '18 at 15:20

























                    answered Nov 14 '18 at 15:01









                    EvgEvg

                    3,81221334




                    3,81221334























                        1














                        I suppose you can use a lambda (and save it in a std::function) to stock values.



                        Something as (caution: code not tested) (thanks to Oliv for a correction)



                        template <typename ... Ts>
                        class Builder
                        {
                        private:
                        std::function<Result()> fn;

                        public:
                        Builder (Ts const & ... ts) : fn{ [=]{ return Result{ts...}; }
                        { }

                        Result build ()
                        { return fn(); }
                        };





                        share|improve this answer





















                        • 1





                          Should not the ts... be captured? Then all these values are going to be stored on the heap, that is really expensive for such a small functionality.

                          – Oliv
                          Nov 14 '18 at 14:47











                        • @Oliv - sure: Builder (Ts & ... ts) : fn{ { return Result{ts...}; }; but it's dangerous; if one construct Builder with a value that is destroyed before the build() calling, the corresponding saved reference is a dangling reference. Maybe it's possible to do something with perfect forwarding, but you have to templatize the constructor.

                          – max66
                          Nov 14 '18 at 15:10








                        • 1





                          Your code is ill formed you must capture! And in order not to have UB parameters have to be captured by value. [=]

                          – Oliv
                          Nov 14 '18 at 19:31











                        • @Oliv - so, it seems to me, is better to receive arguments as Ts const & ...; maybe, this way, some copy are avoided (but I suspect that the compilers optimize this aspect).

                          – max66
                          Nov 14 '18 at 20:09
















                        1














                        I suppose you can use a lambda (and save it in a std::function) to stock values.



                        Something as (caution: code not tested) (thanks to Oliv for a correction)



                        template <typename ... Ts>
                        class Builder
                        {
                        private:
                        std::function<Result()> fn;

                        public:
                        Builder (Ts const & ... ts) : fn{ [=]{ return Result{ts...}; }
                        { }

                        Result build ()
                        { return fn(); }
                        };





                        share|improve this answer





















                        • 1





                          Should not the ts... be captured? Then all these values are going to be stored on the heap, that is really expensive for such a small functionality.

                          – Oliv
                          Nov 14 '18 at 14:47











                        • @Oliv - sure: Builder (Ts & ... ts) : fn{ { return Result{ts...}; }; but it's dangerous; if one construct Builder with a value that is destroyed before the build() calling, the corresponding saved reference is a dangling reference. Maybe it's possible to do something with perfect forwarding, but you have to templatize the constructor.

                          – max66
                          Nov 14 '18 at 15:10








                        • 1





                          Your code is ill formed you must capture! And in order not to have UB parameters have to be captured by value. [=]

                          – Oliv
                          Nov 14 '18 at 19:31











                        • @Oliv - so, it seems to me, is better to receive arguments as Ts const & ...; maybe, this way, some copy are avoided (but I suspect that the compilers optimize this aspect).

                          – max66
                          Nov 14 '18 at 20:09














                        1












                        1








                        1







                        I suppose you can use a lambda (and save it in a std::function) to stock values.



                        Something as (caution: code not tested) (thanks to Oliv for a correction)



                        template <typename ... Ts>
                        class Builder
                        {
                        private:
                        std::function<Result()> fn;

                        public:
                        Builder (Ts const & ... ts) : fn{ [=]{ return Result{ts...}; }
                        { }

                        Result build ()
                        { return fn(); }
                        };





                        share|improve this answer















                        I suppose you can use a lambda (and save it in a std::function) to stock values.



                        Something as (caution: code not tested) (thanks to Oliv for a correction)



                        template <typename ... Ts>
                        class Builder
                        {
                        private:
                        std::function<Result()> fn;

                        public:
                        Builder (Ts const & ... ts) : fn{ [=]{ return Result{ts...}; }
                        { }

                        Result build ()
                        { return fn(); }
                        };






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Nov 14 '18 at 22:25

























                        answered Nov 14 '18 at 14:34









                        max66max66

                        35.5k73964




                        35.5k73964








                        • 1





                          Should not the ts... be captured? Then all these values are going to be stored on the heap, that is really expensive for such a small functionality.

                          – Oliv
                          Nov 14 '18 at 14:47











                        • @Oliv - sure: Builder (Ts & ... ts) : fn{ { return Result{ts...}; }; but it's dangerous; if one construct Builder with a value that is destroyed before the build() calling, the corresponding saved reference is a dangling reference. Maybe it's possible to do something with perfect forwarding, but you have to templatize the constructor.

                          – max66
                          Nov 14 '18 at 15:10








                        • 1





                          Your code is ill formed you must capture! And in order not to have UB parameters have to be captured by value. [=]

                          – Oliv
                          Nov 14 '18 at 19:31











                        • @Oliv - so, it seems to me, is better to receive arguments as Ts const & ...; maybe, this way, some copy are avoided (but I suspect that the compilers optimize this aspect).

                          – max66
                          Nov 14 '18 at 20:09














                        • 1





                          Should not the ts... be captured? Then all these values are going to be stored on the heap, that is really expensive for such a small functionality.

                          – Oliv
                          Nov 14 '18 at 14:47











                        • @Oliv - sure: Builder (Ts & ... ts) : fn{ { return Result{ts...}; }; but it's dangerous; if one construct Builder with a value that is destroyed before the build() calling, the corresponding saved reference is a dangling reference. Maybe it's possible to do something with perfect forwarding, but you have to templatize the constructor.

                          – max66
                          Nov 14 '18 at 15:10








                        • 1





                          Your code is ill formed you must capture! And in order not to have UB parameters have to be captured by value. [=]

                          – Oliv
                          Nov 14 '18 at 19:31











                        • @Oliv - so, it seems to me, is better to receive arguments as Ts const & ...; maybe, this way, some copy are avoided (but I suspect that the compilers optimize this aspect).

                          – max66
                          Nov 14 '18 at 20:09








                        1




                        1





                        Should not the ts... be captured? Then all these values are going to be stored on the heap, that is really expensive for such a small functionality.

                        – Oliv
                        Nov 14 '18 at 14:47





                        Should not the ts... be captured? Then all these values are going to be stored on the heap, that is really expensive for such a small functionality.

                        – Oliv
                        Nov 14 '18 at 14:47













                        @Oliv - sure: Builder (Ts & ... ts) : fn{ { return Result{ts...}; }; but it's dangerous; if one construct Builder with a value that is destroyed before the build() calling, the corresponding saved reference is a dangling reference. Maybe it's possible to do something with perfect forwarding, but you have to templatize the constructor.

                        – max66
                        Nov 14 '18 at 15:10







                        @Oliv - sure: Builder (Ts & ... ts) : fn{ { return Result{ts...}; }; but it's dangerous; if one construct Builder with a value that is destroyed before the build() calling, the corresponding saved reference is a dangling reference. Maybe it's possible to do something with perfect forwarding, but you have to templatize the constructor.

                        – max66
                        Nov 14 '18 at 15:10






                        1




                        1





                        Your code is ill formed you must capture! And in order not to have UB parameters have to be captured by value. [=]

                        – Oliv
                        Nov 14 '18 at 19:31





                        Your code is ill formed you must capture! And in order not to have UB parameters have to be captured by value. [=]

                        – Oliv
                        Nov 14 '18 at 19:31













                        @Oliv - so, it seems to me, is better to receive arguments as Ts const & ...; maybe, this way, some copy are avoided (but I suspect that the compilers optimize this aspect).

                        – max66
                        Nov 14 '18 at 20:09





                        @Oliv - so, it seems to me, is better to receive arguments as Ts const & ...; maybe, this way, some copy are avoided (but I suspect that the compilers optimize this aspect).

                        – max66
                        Nov 14 '18 at 20:09











                        1














                        One of the solutions I found is to pass intermediary tuple<...> that contains the fields and then unpack it using the mechanism described in "unpacking" a tuple to call a matching function pointer :



                        // unpacking helpers
                        template<int ...> struct seq {};

                        template<int N, int ...S>
                        struct gens : gens<N-1, N-1, S...> {};

                        template<int ...S>
                        struct gens<0, S...> {
                        typedef seq<S...> type;
                        };

                        // Builder with 0 fields returns an empty tuple
                        template <class... Ts> class Builder {
                        public:
                        tuple<> compute_tuple() {
                        return {};
                        }
                        };

                        template <class T, class... Ts>
                        class Builder<T, Ts...> : public Builder<Ts...> {
                        public:
                        Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

                        Result build() {
                        // get argument tuple
                        auto arguments = compute_tuple();
                        // use argument tuple as Result's argument
                        return build_recursively(typename gens<1 + sizeof... (Ts)>::type{}, arguments);
                        }

                        protected:
                        // computing tuple - just join current element with superclass' result
                        tuple<T, Ts...> compute_tuple() {
                        const tuple<T> head{field};
                        const tuple<Ts...> tail = Builder<Ts...>::compute_tuple();
                        return tuple_cat(head, tail);
                        }

                        private:
                        template<int ...S>
                        Result build_recursively(seq<S...>, tuple<T, Ts...> data) {
                        // invoked matching Result's constructor
                        return { std::get<S>(data) ... };
                        }

                        const T field;
                        };


                        Then it behaves properly:



                        Builder<string, string> b1{"a", "b"};
                        b1.build(); // invokes Result(string, string)


                        Still, maybe it's possible to do something simpler without that tuple intermediary?






                        share|improve this answer






























                          1














                          One of the solutions I found is to pass intermediary tuple<...> that contains the fields and then unpack it using the mechanism described in "unpacking" a tuple to call a matching function pointer :



                          // unpacking helpers
                          template<int ...> struct seq {};

                          template<int N, int ...S>
                          struct gens : gens<N-1, N-1, S...> {};

                          template<int ...S>
                          struct gens<0, S...> {
                          typedef seq<S...> type;
                          };

                          // Builder with 0 fields returns an empty tuple
                          template <class... Ts> class Builder {
                          public:
                          tuple<> compute_tuple() {
                          return {};
                          }
                          };

                          template <class T, class... Ts>
                          class Builder<T, Ts...> : public Builder<Ts...> {
                          public:
                          Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

                          Result build() {
                          // get argument tuple
                          auto arguments = compute_tuple();
                          // use argument tuple as Result's argument
                          return build_recursively(typename gens<1 + sizeof... (Ts)>::type{}, arguments);
                          }

                          protected:
                          // computing tuple - just join current element with superclass' result
                          tuple<T, Ts...> compute_tuple() {
                          const tuple<T> head{field};
                          const tuple<Ts...> tail = Builder<Ts...>::compute_tuple();
                          return tuple_cat(head, tail);
                          }

                          private:
                          template<int ...S>
                          Result build_recursively(seq<S...>, tuple<T, Ts...> data) {
                          // invoked matching Result's constructor
                          return { std::get<S>(data) ... };
                          }

                          const T field;
                          };


                          Then it behaves properly:



                          Builder<string, string> b1{"a", "b"};
                          b1.build(); // invokes Result(string, string)


                          Still, maybe it's possible to do something simpler without that tuple intermediary?






                          share|improve this answer




























                            1












                            1








                            1







                            One of the solutions I found is to pass intermediary tuple<...> that contains the fields and then unpack it using the mechanism described in "unpacking" a tuple to call a matching function pointer :



                            // unpacking helpers
                            template<int ...> struct seq {};

                            template<int N, int ...S>
                            struct gens : gens<N-1, N-1, S...> {};

                            template<int ...S>
                            struct gens<0, S...> {
                            typedef seq<S...> type;
                            };

                            // Builder with 0 fields returns an empty tuple
                            template <class... Ts> class Builder {
                            public:
                            tuple<> compute_tuple() {
                            return {};
                            }
                            };

                            template <class T, class... Ts>
                            class Builder<T, Ts...> : public Builder<Ts...> {
                            public:
                            Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

                            Result build() {
                            // get argument tuple
                            auto arguments = compute_tuple();
                            // use argument tuple as Result's argument
                            return build_recursively(typename gens<1 + sizeof... (Ts)>::type{}, arguments);
                            }

                            protected:
                            // computing tuple - just join current element with superclass' result
                            tuple<T, Ts...> compute_tuple() {
                            const tuple<T> head{field};
                            const tuple<Ts...> tail = Builder<Ts...>::compute_tuple();
                            return tuple_cat(head, tail);
                            }

                            private:
                            template<int ...S>
                            Result build_recursively(seq<S...>, tuple<T, Ts...> data) {
                            // invoked matching Result's constructor
                            return { std::get<S>(data) ... };
                            }

                            const T field;
                            };


                            Then it behaves properly:



                            Builder<string, string> b1{"a", "b"};
                            b1.build(); // invokes Result(string, string)


                            Still, maybe it's possible to do something simpler without that tuple intermediary?






                            share|improve this answer















                            One of the solutions I found is to pass intermediary tuple<...> that contains the fields and then unpack it using the mechanism described in "unpacking" a tuple to call a matching function pointer :



                            // unpacking helpers
                            template<int ...> struct seq {};

                            template<int N, int ...S>
                            struct gens : gens<N-1, N-1, S...> {};

                            template<int ...S>
                            struct gens<0, S...> {
                            typedef seq<S...> type;
                            };

                            // Builder with 0 fields returns an empty tuple
                            template <class... Ts> class Builder {
                            public:
                            tuple<> compute_tuple() {
                            return {};
                            }
                            };

                            template <class T, class... Ts>
                            class Builder<T, Ts...> : public Builder<Ts...> {
                            public:
                            Builder(T t, Ts... ts) : Builder<Ts...>(ts...), tail(t) {}

                            Result build() {
                            // get argument tuple
                            auto arguments = compute_tuple();
                            // use argument tuple as Result's argument
                            return build_recursively(typename gens<1 + sizeof... (Ts)>::type{}, arguments);
                            }

                            protected:
                            // computing tuple - just join current element with superclass' result
                            tuple<T, Ts...> compute_tuple() {
                            const tuple<T> head{field};
                            const tuple<Ts...> tail = Builder<Ts...>::compute_tuple();
                            return tuple_cat(head, tail);
                            }

                            private:
                            template<int ...S>
                            Result build_recursively(seq<S...>, tuple<T, Ts...> data) {
                            // invoked matching Result's constructor
                            return { std::get<S>(data) ... };
                            }

                            const T field;
                            };


                            Then it behaves properly:



                            Builder<string, string> b1{"a", "b"};
                            b1.build(); // invokes Result(string, string)


                            Still, maybe it's possible to do something simpler without that tuple intermediary?







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 15 '18 at 2:30

























                            answered Nov 14 '18 at 14:25









                            Adam KotwasinskiAdam Kotwasinski

                            2,538827




                            2,538827






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53302451%2fusing-fields-stored-in-variadic-data-structure-as-method-arguments%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                這個網誌中的熱門文章

                                Academy of Television Arts & Sciences

                                L'Équipe

                                1995 France bombings