The variadic template constructor of my class cannot modify my class members, why is that so?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







17















I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.



What I have tried:




  • using pointer int* count instead of int count


  • using a setter to set the counter



I have already googled around for hours, but cannot find a solving answer.



Header file "test.h":



#include <cstdarg>
#include <iostream>

class Counter {
private:
int count = 0;
int tmp;

public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};


main.cpp:



#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}


The output I got:



start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...









share|improve this question









New contributor




PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





















  • Perhaps the intention here is for count to be static, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp.

    – Jonathan Mee
    Apr 13 at 14:16


















17















I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.



What I have tried:




  • using pointer int* count instead of int count


  • using a setter to set the counter



I have already googled around for hours, but cannot find a solving answer.



Header file "test.h":



#include <cstdarg>
#include <iostream>

class Counter {
private:
int count = 0;
int tmp;

public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};


main.cpp:



#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}


The output I got:



start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...









share|improve this question









New contributor




PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





















  • Perhaps the intention here is for count to be static, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp.

    – Jonathan Mee
    Apr 13 at 14:16














17












17








17








I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.



What I have tried:




  • using pointer int* count instead of int count


  • using a setter to set the counter



I have already googled around for hours, but cannot find a solving answer.



Header file "test.h":



#include <cstdarg>
#include <iostream>

class Counter {
private:
int count = 0;
int tmp;

public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};


main.cpp:



#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}


The output I got:



start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...









share|improve this question









New contributor




PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












I've been working on a task we got by our professor, where I have to work around a variadic template class.
The problem is, I cannot modify the class members within the recursive constructor. I cannot figure out why this is the case, as soon as it goes into the next constructor call, it will discard my changes on the variable.



What I have tried:




  • using pointer int* count instead of int count


  • using a setter to set the counter



I have already googled around for hours, but cannot find a solving answer.



Header file "test.h":



#include <cstdarg>
#include <iostream>

class Counter {
private:
int count = 0;
int tmp;

public:
template <typename... Rest> Counter (int t, Rest... rest) {
count++;
std::cout << "start recursive number " << count << "...n";
Counter(rest ...);
tmp = t;
std::cout << "end recursive number " << count << "...n";
}
Counter (int t) {
count++;
tmp = t;
std::cout << "reached end of recursive -> " << count << "n";
}
};


main.cpp:



#include "test.h"
int main () {
Counter a {0, 1, 2, 3, 4};
}


The output I got:



start recursive number 1...
start recursive number 1...
start recursive number 1...
start recursive number 1...
reached end of recursive -> 1
end recursive number 1...
end recursive number 1...
end recursive number 1...
end recursive number 1...






c++ c++11 recursion variadic-templates






share|improve this question









New contributor




PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited Apr 13 at 14:05









TrebledJ

3,98921431




3,98921431






New contributor




PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Apr 13 at 13:06









PrettyCoffeePrettyCoffee

864




864




New contributor




PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






PrettyCoffee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.













  • Perhaps the intention here is for count to be static, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp.

    – Jonathan Mee
    Apr 13 at 14:16



















  • Perhaps the intention here is for count to be static, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp.

    – Jonathan Mee
    Apr 13 at 14:16

















Perhaps the intention here is for count to be static, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp.

– Jonathan Mee
Apr 13 at 14:16





Perhaps the intention here is for count to be static, I'm not certain if that's considered modifying the variable? Either way I imagine your intent is to print tmp.

– Jonathan Mee
Apr 13 at 14:16












2 Answers
2






active

oldest

votes


















24














Counter(rest ...); creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count therefore you get stream of 1 1 1 1



If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:



template <typename... Rest> Counter (int t, Rest... rest)
: Counter{rest...}
{
count++;
std::cout << "start recursive number " << count << "...n";
tmp = t;
std::cout << "end recursive number " << count << "...n";
}





share|improve this answer

































    12














    As explained by VTT, calling Counter() inside the body of the constructor create a new Counter() object.



    You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.



    I also would advise you against initialization (and modifications) of member object inside the body of contructors.



    If your target is initialize count with the number of the arguments and tmp with the value of the last argument, I propose the following ("tag dispatching" based) solution



    class Counter
    {
    private:
    struct tag
    { };

    int count = 0;
    int tmp;

    Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
    { std::cout << "end: " << tmp << ", " <<count << "n"; }

    template <typename... Rest>
    Counter (tag t0, std::size_t c0, int t, Rest... rest)
    : Counter{t0, c0, rest...}
    { std::cout << "recursion: " << tmp << ", " << count << "n"; }

    public:
    template <typename... Rest>
    Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
    { std::cout << "start: " << tmp << ", " << count << "n"; }
    };


    You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest... to a method (maybe static and also constexpr, if you want) used to initialize tmp



    class Counter
    {
    private:
    int count = 0;
    int tmp;

    static int getLastInt (int i)
    { return i; }

    template <typename ... Rest>
    static int getLastInt (int, Rest ... rs)
    { return getLastInt(rs...); }

    public:
    template <typename... Rest>
    Counter (Rest... rest)
    : count(sizeof...(Rest)), tmp{getLastInt(rest...)}
    { std::cout << tmp << ", " << count << "n"; }
    };


    Off Topic: to be precise, your Counter class isn't "a variadic template class".



    It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).



    -- EDIT --



    The OP asks




    What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?




    A static const (maybe also constexpr) make sense only if the counter is a common value between all the instances of the class.



    At the moment doesn't make sense because your Counter accept initialization lists of different length.



    But suppose that number of the argument of the constructor is a template parameter (say N)... in that case count is simply N and can be static constexpr. You can define a std::array<int, N> for the values (also a int[N] but I suggest to avoid to use C-style arrays, when possible, and use std::array instead) and, making the constructor constexpr, you can impose the compile time initialization.



    The following is a full compiling C++14 example (uses std::make_index_sequence and std::index_sequence that, unfortunately, are available only starting from C++14).



    Observe that I've defined the f8 variable in main() as constexpr: only this way you can impose (pretending there isn't the as-is rule) that f8 is initialized compile-time



    #include <array>
    #include <iostream>
    #include <type_traits>

    template <typename T, std::size_t>
    using getType = T;

    template <std::size_t N, typename = std::make_index_sequence<N>>
    struct foo;

    template <std::size_t N, std::size_t ... Is>
    struct foo<N, std::index_sequence<Is...>>
    {
    static_assert( sizeof...(Is), "!" );

    static constexpr auto count = N;

    const std::array<int, N> arr;

    constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
    { }
    };

    int main ()
    {
    constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };

    for ( auto const & i : f8.arr )
    std::cout << i << ' ';

    std::cout << std::endl;
    }


    If you can use a C++17 enabled compiler, you can also use a deduction guide for foo



    template <typename ... Args>
    foo(Args...) -> foo<sizeof...(Args)>;


    so there is no needs to explicate the template argument defining f8



    // .......VVV  no more "<8u>"
    constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };


    because it's deduced from the number of the argument of the constructor.






    share|improve this answer


























    • Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?

      – PrettyCoffee
      Apr 13 at 19:03











    • @PrettyCoffee - Let me think... Take in count that a static variable is a variable common to all instances of the class, so a static count variable (constant, moreover) make sense only if the count value is common to all instances of Counter. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.

      – max66
      Apr 13 at 20:30











    • @PrettyCoffee - answer improved; hope this helps.

      – max66
      Apr 13 at 20:55












    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
    });


    }
    });






    PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.










    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55665792%2fthe-variadic-template-constructor-of-my-class-cannot-modify-my-class-members-wh%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    24














    Counter(rest ...); creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count therefore you get stream of 1 1 1 1



    If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:



    template <typename... Rest> Counter (int t, Rest... rest)
    : Counter{rest...}
    {
    count++;
    std::cout << "start recursive number " << count << "...n";
    tmp = t;
    std::cout << "end recursive number " << count << "...n";
    }





    share|improve this answer






























      24














      Counter(rest ...); creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count therefore you get stream of 1 1 1 1



      If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:



      template <typename... Rest> Counter (int t, Rest... rest)
      : Counter{rest...}
      {
      count++;
      std::cout << "start recursive number " << count << "...n";
      tmp = t;
      std::cout << "end recursive number " << count << "...n";
      }





      share|improve this answer




























        24












        24








        24







        Counter(rest ...); creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count therefore you get stream of 1 1 1 1



        If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:



        template <typename... Rest> Counter (int t, Rest... rest)
        : Counter{rest...}
        {
        count++;
        std::cout << "start recursive number " << count << "...n";
        tmp = t;
        std::cout << "end recursive number " << count << "...n";
        }





        share|improve this answer















        Counter(rest ...); creates an unnamed temporary object, it does not recursively invoke constructor for this object. Each object is spawned with its own count therefore you get stream of 1 1 1 1



        If you want to delegate object initialization to different constructor then it should be present in member initialization list. This does not seem like a good idea though:



        template <typename... Rest> Counter (int t, Rest... rest)
        : Counter{rest...}
        {
        count++;
        std::cout << "start recursive number " << count << "...n";
        tmp = t;
        std::cout << "end recursive number " << count << "...n";
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Apr 13 at 13:16

























        answered Apr 13 at 13:10









        VTTVTT

        26.4k42550




        26.4k42550

























            12














            As explained by VTT, calling Counter() inside the body of the constructor create a new Counter() object.



            You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.



            I also would advise you against initialization (and modifications) of member object inside the body of contructors.



            If your target is initialize count with the number of the arguments and tmp with the value of the last argument, I propose the following ("tag dispatching" based) solution



            class Counter
            {
            private:
            struct tag
            { };

            int count = 0;
            int tmp;

            Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
            { std::cout << "end: " << tmp << ", " <<count << "n"; }

            template <typename... Rest>
            Counter (tag t0, std::size_t c0, int t, Rest... rest)
            : Counter{t0, c0, rest...}
            { std::cout << "recursion: " << tmp << ", " << count << "n"; }

            public:
            template <typename... Rest>
            Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
            { std::cout << "start: " << tmp << ", " << count << "n"; }
            };


            You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest... to a method (maybe static and also constexpr, if you want) used to initialize tmp



            class Counter
            {
            private:
            int count = 0;
            int tmp;

            static int getLastInt (int i)
            { return i; }

            template <typename ... Rest>
            static int getLastInt (int, Rest ... rs)
            { return getLastInt(rs...); }

            public:
            template <typename... Rest>
            Counter (Rest... rest)
            : count(sizeof...(Rest)), tmp{getLastInt(rest...)}
            { std::cout << tmp << ", " << count << "n"; }
            };


            Off Topic: to be precise, your Counter class isn't "a variadic template class".



            It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).



            -- EDIT --



            The OP asks




            What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?




            A static const (maybe also constexpr) make sense only if the counter is a common value between all the instances of the class.



            At the moment doesn't make sense because your Counter accept initialization lists of different length.



            But suppose that number of the argument of the constructor is a template parameter (say N)... in that case count is simply N and can be static constexpr. You can define a std::array<int, N> for the values (also a int[N] but I suggest to avoid to use C-style arrays, when possible, and use std::array instead) and, making the constructor constexpr, you can impose the compile time initialization.



            The following is a full compiling C++14 example (uses std::make_index_sequence and std::index_sequence that, unfortunately, are available only starting from C++14).



            Observe that I've defined the f8 variable in main() as constexpr: only this way you can impose (pretending there isn't the as-is rule) that f8 is initialized compile-time



            #include <array>
            #include <iostream>
            #include <type_traits>

            template <typename T, std::size_t>
            using getType = T;

            template <std::size_t N, typename = std::make_index_sequence<N>>
            struct foo;

            template <std::size_t N, std::size_t ... Is>
            struct foo<N, std::index_sequence<Is...>>
            {
            static_assert( sizeof...(Is), "!" );

            static constexpr auto count = N;

            const std::array<int, N> arr;

            constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
            { }
            };

            int main ()
            {
            constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };

            for ( auto const & i : f8.arr )
            std::cout << i << ' ';

            std::cout << std::endl;
            }


            If you can use a C++17 enabled compiler, you can also use a deduction guide for foo



            template <typename ... Args>
            foo(Args...) -> foo<sizeof...(Args)>;


            so there is no needs to explicate the template argument defining f8



            // .......VVV  no more "<8u>"
            constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };


            because it's deduced from the number of the argument of the constructor.






            share|improve this answer


























            • Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?

              – PrettyCoffee
              Apr 13 at 19:03











            • @PrettyCoffee - Let me think... Take in count that a static variable is a variable common to all instances of the class, so a static count variable (constant, moreover) make sense only if the count value is common to all instances of Counter. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.

              – max66
              Apr 13 at 20:30











            • @PrettyCoffee - answer improved; hope this helps.

              – max66
              Apr 13 at 20:55
















            12














            As explained by VTT, calling Counter() inside the body of the constructor create a new Counter() object.



            You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.



            I also would advise you against initialization (and modifications) of member object inside the body of contructors.



            If your target is initialize count with the number of the arguments and tmp with the value of the last argument, I propose the following ("tag dispatching" based) solution



            class Counter
            {
            private:
            struct tag
            { };

            int count = 0;
            int tmp;

            Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
            { std::cout << "end: " << tmp << ", " <<count << "n"; }

            template <typename... Rest>
            Counter (tag t0, std::size_t c0, int t, Rest... rest)
            : Counter{t0, c0, rest...}
            { std::cout << "recursion: " << tmp << ", " << count << "n"; }

            public:
            template <typename... Rest>
            Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
            { std::cout << "start: " << tmp << ", " << count << "n"; }
            };


            You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest... to a method (maybe static and also constexpr, if you want) used to initialize tmp



            class Counter
            {
            private:
            int count = 0;
            int tmp;

            static int getLastInt (int i)
            { return i; }

            template <typename ... Rest>
            static int getLastInt (int, Rest ... rs)
            { return getLastInt(rs...); }

            public:
            template <typename... Rest>
            Counter (Rest... rest)
            : count(sizeof...(Rest)), tmp{getLastInt(rest...)}
            { std::cout << tmp << ", " << count << "n"; }
            };


            Off Topic: to be precise, your Counter class isn't "a variadic template class".



            It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).



            -- EDIT --



            The OP asks




            What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?




            A static const (maybe also constexpr) make sense only if the counter is a common value between all the instances of the class.



            At the moment doesn't make sense because your Counter accept initialization lists of different length.



            But suppose that number of the argument of the constructor is a template parameter (say N)... in that case count is simply N and can be static constexpr. You can define a std::array<int, N> for the values (also a int[N] but I suggest to avoid to use C-style arrays, when possible, and use std::array instead) and, making the constructor constexpr, you can impose the compile time initialization.



            The following is a full compiling C++14 example (uses std::make_index_sequence and std::index_sequence that, unfortunately, are available only starting from C++14).



            Observe that I've defined the f8 variable in main() as constexpr: only this way you can impose (pretending there isn't the as-is rule) that f8 is initialized compile-time



            #include <array>
            #include <iostream>
            #include <type_traits>

            template <typename T, std::size_t>
            using getType = T;

            template <std::size_t N, typename = std::make_index_sequence<N>>
            struct foo;

            template <std::size_t N, std::size_t ... Is>
            struct foo<N, std::index_sequence<Is...>>
            {
            static_assert( sizeof...(Is), "!" );

            static constexpr auto count = N;

            const std::array<int, N> arr;

            constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
            { }
            };

            int main ()
            {
            constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };

            for ( auto const & i : f8.arr )
            std::cout << i << ' ';

            std::cout << std::endl;
            }


            If you can use a C++17 enabled compiler, you can also use a deduction guide for foo



            template <typename ... Args>
            foo(Args...) -> foo<sizeof...(Args)>;


            so there is no needs to explicate the template argument defining f8



            // .......VVV  no more "<8u>"
            constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };


            because it's deduced from the number of the argument of the constructor.






            share|improve this answer


























            • Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?

              – PrettyCoffee
              Apr 13 at 19:03











            • @PrettyCoffee - Let me think... Take in count that a static variable is a variable common to all instances of the class, so a static count variable (constant, moreover) make sense only if the count value is common to all instances of Counter. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.

              – max66
              Apr 13 at 20:30











            • @PrettyCoffee - answer improved; hope this helps.

              – max66
              Apr 13 at 20:55














            12












            12








            12







            As explained by VTT, calling Counter() inside the body of the constructor create a new Counter() object.



            You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.



            I also would advise you against initialization (and modifications) of member object inside the body of contructors.



            If your target is initialize count with the number of the arguments and tmp with the value of the last argument, I propose the following ("tag dispatching" based) solution



            class Counter
            {
            private:
            struct tag
            { };

            int count = 0;
            int tmp;

            Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
            { std::cout << "end: " << tmp << ", " <<count << "n"; }

            template <typename... Rest>
            Counter (tag t0, std::size_t c0, int t, Rest... rest)
            : Counter{t0, c0, rest...}
            { std::cout << "recursion: " << tmp << ", " << count << "n"; }

            public:
            template <typename... Rest>
            Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
            { std::cout << "start: " << tmp << ", " << count << "n"; }
            };


            You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest... to a method (maybe static and also constexpr, if you want) used to initialize tmp



            class Counter
            {
            private:
            int count = 0;
            int tmp;

            static int getLastInt (int i)
            { return i; }

            template <typename ... Rest>
            static int getLastInt (int, Rest ... rs)
            { return getLastInt(rs...); }

            public:
            template <typename... Rest>
            Counter (Rest... rest)
            : count(sizeof...(Rest)), tmp{getLastInt(rest...)}
            { std::cout << tmp << ", " << count << "n"; }
            };


            Off Topic: to be precise, your Counter class isn't "a variadic template class".



            It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).



            -- EDIT --



            The OP asks




            What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?




            A static const (maybe also constexpr) make sense only if the counter is a common value between all the instances of the class.



            At the moment doesn't make sense because your Counter accept initialization lists of different length.



            But suppose that number of the argument of the constructor is a template parameter (say N)... in that case count is simply N and can be static constexpr. You can define a std::array<int, N> for the values (also a int[N] but I suggest to avoid to use C-style arrays, when possible, and use std::array instead) and, making the constructor constexpr, you can impose the compile time initialization.



            The following is a full compiling C++14 example (uses std::make_index_sequence and std::index_sequence that, unfortunately, are available only starting from C++14).



            Observe that I've defined the f8 variable in main() as constexpr: only this way you can impose (pretending there isn't the as-is rule) that f8 is initialized compile-time



            #include <array>
            #include <iostream>
            #include <type_traits>

            template <typename T, std::size_t>
            using getType = T;

            template <std::size_t N, typename = std::make_index_sequence<N>>
            struct foo;

            template <std::size_t N, std::size_t ... Is>
            struct foo<N, std::index_sequence<Is...>>
            {
            static_assert( sizeof...(Is), "!" );

            static constexpr auto count = N;

            const std::array<int, N> arr;

            constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
            { }
            };

            int main ()
            {
            constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };

            for ( auto const & i : f8.arr )
            std::cout << i << ' ';

            std::cout << std::endl;
            }


            If you can use a C++17 enabled compiler, you can also use a deduction guide for foo



            template <typename ... Args>
            foo(Args...) -> foo<sizeof...(Args)>;


            so there is no needs to explicate the template argument defining f8



            // .......VVV  no more "<8u>"
            constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };


            because it's deduced from the number of the argument of the constructor.






            share|improve this answer















            As explained by VTT, calling Counter() inside the body of the constructor create a new Counter() object.



            You can call, recursively, the contructors but you have to do this in the initialization list: look for "delegating contructors" for more informations.



            I also would advise you against initialization (and modifications) of member object inside the body of contructors.



            If your target is initialize count with the number of the arguments and tmp with the value of the last argument, I propose the following ("tag dispatching" based) solution



            class Counter
            {
            private:
            struct tag
            { };

            int count = 0;
            int tmp;

            Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
            { std::cout << "end: " << tmp << ", " <<count << "n"; }

            template <typename... Rest>
            Counter (tag t0, std::size_t c0, int t, Rest... rest)
            : Counter{t0, c0, rest...}
            { std::cout << "recursion: " << tmp << ", " << count << "n"; }

            public:
            template <typename... Rest>
            Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
            { std::cout << "start: " << tmp << ", " << count << "n"; }
            };


            You can also avoid tag-dispatching and constructor recursion delegating the recursion about rest... to a method (maybe static and also constexpr, if you want) used to initialize tmp



            class Counter
            {
            private:
            int count = 0;
            int tmp;

            static int getLastInt (int i)
            { return i; }

            template <typename ... Rest>
            static int getLastInt (int, Rest ... rs)
            { return getLastInt(rs...); }

            public:
            template <typename... Rest>
            Counter (Rest... rest)
            : count(sizeof...(Rest)), tmp{getLastInt(rest...)}
            { std::cout << tmp << ", " << count << "n"; }
            };


            Off Topic: to be precise, your Counter class isn't "a variadic template class".



            It's an ordinary (not template) class with one (two, in my first solution) variadic template constructor(s).



            -- EDIT --



            The OP asks




            What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?




            A static const (maybe also constexpr) make sense only if the counter is a common value between all the instances of the class.



            At the moment doesn't make sense because your Counter accept initialization lists of different length.



            But suppose that number of the argument of the constructor is a template parameter (say N)... in that case count is simply N and can be static constexpr. You can define a std::array<int, N> for the values (also a int[N] but I suggest to avoid to use C-style arrays, when possible, and use std::array instead) and, making the constructor constexpr, you can impose the compile time initialization.



            The following is a full compiling C++14 example (uses std::make_index_sequence and std::index_sequence that, unfortunately, are available only starting from C++14).



            Observe that I've defined the f8 variable in main() as constexpr: only this way you can impose (pretending there isn't the as-is rule) that f8 is initialized compile-time



            #include <array>
            #include <iostream>
            #include <type_traits>

            template <typename T, std::size_t>
            using getType = T;

            template <std::size_t N, typename = std::make_index_sequence<N>>
            struct foo;

            template <std::size_t N, std::size_t ... Is>
            struct foo<N, std::index_sequence<Is...>>
            {
            static_assert( sizeof...(Is), "!" );

            static constexpr auto count = N;

            const std::array<int, N> arr;

            constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
            { }
            };

            int main ()
            {
            constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };

            for ( auto const & i : f8.arr )
            std::cout << i << ' ';

            std::cout << std::endl;
            }


            If you can use a C++17 enabled compiler, you can also use a deduction guide for foo



            template <typename ... Args>
            foo(Args...) -> foo<sizeof...(Args)>;


            so there is no needs to explicate the template argument defining f8



            // .......VVV  no more "<8u>"
            constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };


            because it's deduced from the number of the argument of the constructor.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Apr 13 at 20:55

























            answered Apr 13 at 13:33









            max66max66

            39.5k74575




            39.5k74575













            • Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?

              – PrettyCoffee
              Apr 13 at 19:03











            • @PrettyCoffee - Let me think... Take in count that a static variable is a variable common to all instances of the class, so a static count variable (constant, moreover) make sense only if the count value is common to all instances of Counter. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.

              – max66
              Apr 13 at 20:30











            • @PrettyCoffee - answer improved; hope this helps.

              – max66
              Apr 13 at 20:55



















            • Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?

              – PrettyCoffee
              Apr 13 at 19:03











            • @PrettyCoffee - Let me think... Take in count that a static variable is a variable common to all instances of the class, so a static count variable (constant, moreover) make sense only if the count value is common to all instances of Counter. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.

              – max66
              Apr 13 at 20:30











            • @PrettyCoffee - answer improved; hope this helps.

              – max66
              Apr 13 at 20:55

















            Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?

            – PrettyCoffee
            Apr 13 at 19:03





            Thank u very much for the hint, that helped a lot! What if I need to get the count as a static const variable and an int array with the length of the counter within compile time and as class members? (Array will be filled with all constructor arguments) Is this within the C++ possibilitys?

            – PrettyCoffee
            Apr 13 at 19:03













            @PrettyCoffee - Let me think... Take in count that a static variable is a variable common to all instances of the class, so a static count variable (constant, moreover) make sense only if the count value is common to all instances of Counter. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.

            – max66
            Apr 13 at 20:30





            @PrettyCoffee - Let me think... Take in count that a static variable is a variable common to all instances of the class, so a static count variable (constant, moreover) make sense only if the count value is common to all instances of Counter. At the moment do not make sense because you can call the constructor of different instances with different number of arguments. It's different if the number of the template argument is a template parameter of the class. Give me some minutes and I prepare an example of what I mean.

            – max66
            Apr 13 at 20:30













            @PrettyCoffee - answer improved; hope this helps.

            – max66
            Apr 13 at 20:55





            @PrettyCoffee - answer improved; hope this helps.

            – max66
            Apr 13 at 20:55










            PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.













            PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.












            PrettyCoffee is a new contributor. Be nice, and check out our Code of Conduct.
















            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%2f55665792%2fthe-variadic-template-constructor-of-my-class-cannot-modify-my-class-members-wh%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







            Popular posts from this blog

            Plaza Victoria

            Puebla de Zaragoza

            Musa