0

I am trying to make a code snippet generic, but I have trouble doing that as I don't totally understand how the technique used in the code works.

I got the code from another question : C++17 construct array in stack using choosen constructor (same constructor parameter values for each array entry)

Here is the code based on the first response of this post, that is for some reason not working with a size above 88 : http://ideone.com/WDlNwd

#include <iostream>
#include <utility>

struct A1 {
    A1() {
        printf("A1() called\n");
    }

    A1(std::size_t i) {
        printf("A1(%d) called\n", i);
    }

    A1(std::size_t i, std::size_t j) {
        printf("A1(%d, %d) called\n", i, j);
    }
};

struct A2 {
    A2(std::size_t i, std::size_t j, double k) {
        printf("A2(%d, %d, %lf) called\n", i, j, k);
    }
};

template <class T, size_t Size>
class B {
    template<typename Arg1, typename ...Args, size_t... Is>
    B(std::index_sequence<Is...>, const Arg1 &arg1, const Args &...args) :
    tab{ {(void(Is), arg1), args... }... }
    {}

    public:

    T tab[Size];

    B() = default;

    template<typename ...Args>
    B(const Args &...args)
        : B(std::make_index_sequence<Size>(), args...) {}
};

int main() {
    static constexpr size_t Size = 100;
    B<A1, Size> b1(11, 17);
    B<A1, Size> b1a(11);
    B<A1, Size> b1b;
    B<A2, Size> b2(11, 17, 1.2);
    return 0;
}

Thanks

Community
  • 1
  • 1
infiniteLoop
  • 383
  • 2
  • 12
  • 2
    You should not `std::forward` an argument more than once. You never know when that's going to provoke a move. If you want to prevent that, then you should take arguments as `const &` rather than as forwarding references. – Nicol Bolas Jan 02 '17 at 15:52
  • The STL implementation of std::vector::emplace_back() is using exactly the same construct as mine. I used the pattern found in the STL code in the purpose to avoid to do something bad. Do you have an example when it could produce a move or a copy ? – infiniteLoop Jan 02 '17 at 16:23
  • @mikeDundee I think `emplace_back` uses parameters only once, no? My understanding of NicolBolas's comment is that `std::forward` can forward given r-value reference only once as it might be consumed in a first usage and then the reference may point to zero'd object... – W.F. Jan 02 '17 at 16:38
  • Ah yes ! Thank you very much. I found more information here : http://stackoverflow.com/questions/7257144/when-to-use-stdforward-to-forward-arguments – infiniteLoop Jan 02 '17 at 16:46
  • Possible duplicate of [C++17 construct array in stack using choosen constructor (same constructor parameter values for each array entry)](http://stackoverflow.com/questions/41428365/c17-construct-array-in-stack-using-choosen-constructor-same-constructor-param) – rocambille Jan 02 '17 at 17:52
  • @wasthishelpful : Not exactly because the solution of the other question is not working in a generic case when we have parameters of the type size_t for example (see my comment below) – infiniteLoop Jan 02 '17 at 20:49
  • @mikeDundee this should have been a comment to the solution, and you should have edited your other question. Same author, same title, one hour between the two questions: that's a duplicate – rocambille Jan 02 '17 at 21:49
  • @wasthishelpful : The code in the question is not the same, Is it possible to put code in a comment ? – infiniteLoop Jan 03 '17 at 08:25
  • @mikeDundee it is possible to **edit** a question to modify and/or add information or different code. Read [help tour](http://stackoverflow.com/tour) until the part "Improve posts by editing or commenting" – rocambille Jan 03 '17 at 08:52
  • @wasthishelpful : Ok and where the person who will respond to my edit will put his answer ? The answer being different to the previous one, It is not sure that the previous person will respond again. Should I unaccept the other response and accept a new one responding to my edit ? – infiniteLoop Jan 03 '17 at 10:11
  • @mikeDundee you shouldn't have accepted an answer in the first place since it wasn't answering your question since you wasn't asking your question. You should have edited your question and added a comment to the answer to let its author knows it was edited. Now what could be a good idea would be to edit this question, change the title for one different from your previous question, and reference your previous question with explanations on why it is different and why you need a new answer – rocambille Jan 03 '17 at 10:16
  • @wasthishelpful : Ok I will do that – infiniteLoop Jan 03 '17 at 10:20
  • @NicolBolas : A notable exception is forwarding to `std::get<>`, where you want to forward once per unique tuple index (/tuple type/array index/etc.). – ildjarn Jan 03 '17 at 22:53

1 Answers1

1

The answer is essentially the same as the answer you got on the last one. The only difference is that you have to special-case passing zero parameters. And adjust the order of the index_sequence parameter:

struct B {
    A tab[100];

    //Note: feel free to use SFINAE to make this go away
    //if `A` is not default-constructible.
    B() = default;

    template<typename ...Args>
    B(const Args &...args)
        : B(std::make_index_sequence<100>(), args...) {}

private:

    template<typename Arg1, typename ...Args, size_t... Is>
    B(std::index_sequence<Is...>, const Arg1 &arg1, const Args &...args)
        : tab{ {(void(Is), arg1), args... }... } {}
};
Community
  • 1
  • 1
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thank you but this is not working if the parameters are of the type std::size_t : http://ideone.com/WDlNwd – infiniteLoop Jan 02 '17 at 20:44
  • @mikeDundee: Separate what parameter packs? The problem is the narrowing conversion of `int` arguments to `size_t` arguments which list-initialization forbids. I can't fix list-initialization stupidity. So you have two choices: you can [cast the arguments when you create your `B`s](http://ideone.com/5Tpqgx). Or you can construct the type `A` by constructor syntax instead of list syntax. Which means it won't work for aggregates. – Nicol Bolas Jan 02 '17 at 21:28
  • I don't know because your solution is working with an array size of 87 or 88 and below but not above, this is odd. Sorry I don't understand how the list initialization is expanding and I though that the index sequence was a variadic parameter but this is not. – infiniteLoop Jan 03 '17 at 08:19