Declaring and defining template, and specialising them2019 Community Moderator ElectionDifference between instantiation and specialization in c++ templatesUse 'class' or 'typename' for template parameters?Why can templates only be implemented in the header file?Where and why do I have to put the “template” and “typename” keywords?error C2065: 'cout' : undeclared identifierPretty-print C++ STL containersSpecialisation of function template in another class/namespace?C++11 make_pair with specified template parameters doesn't compileImage Processing: Algorithm Improvement for 'Coca-Cola Can' RecognitionIs there some trick that would allow me to pass stream manipulators to a variadic template function?std::atomic_is_lock_free(shared_ptr<T>*) didn't compile

Find longest word in a string: are any of these algorithms good?

In the late 1940’s to early 1950’s what technology was available that could melt a LOT of ice?

How do I express some one as a black person?

Is it possible to avoid unpacking when merging Association?

Why does Captain Marvel assume the people on this planet know this?

How to draw cubes in a 3 dimensional plane

What's wrong with this bogus proof?

Bash script should only kill those instances of another script's that it has launched

Do f-stop and exposure time perfectly cancel?

Accountant/ lawyer will not return my call

Is it necessary to separate DC power cables and data cables?

Virginia employer terminated employee and wants signing bonus returned

Are there historical instances of the capital of a colonising country being temporarily or permanently shifted to one of its colonies?

In the quantum hamiltonian, why does kinetic energy turn into an operator while potential doesn't?

Error during using callback start_page_number in lualatex

Does "Until when" sound natural for native speakers?

Plausibility of Mushroom Buildings

How does one describe somebody who is bi-racial?

weren't playing vs didn't play

How many characters using PHB rules does it take to be able to have access to any PHB spell at the start of an adventuring day?

How can I ensure my trip to the UK will not have to be cancelled because of Brexit?

Why doesn't this Google Translate ad use the word "Translation" instead of "Translate"?

How to write ı (i without dot) character in pgf-pie

Examples of a statistic that is not independent of sample's distribution?



Declaring and defining template, and specialising them



2019 Community Moderator ElectionDifference between instantiation and specialization in c++ templatesUse 'class' or 'typename' for template parameters?Why can templates only be implemented in the header file?Where and why do I have to put the “template” and “typename” keywords?error C2065: 'cout' : undeclared identifierPretty-print C++ STL containersSpecialisation of function template in another class/namespace?C++11 make_pair with specified template parameters doesn't compileImage Processing: Algorithm Improvement for 'Coca-Cola Can' RecognitionIs there some trick that would allow me to pass stream manipulators to a variadic template function?std::atomic_is_lock_free(shared_ptr<T>*) didn't compile










7















I'm trying to understand the below example, but I'm a bit confused from the three different template and struct declarations.



Could you please describe what will happen for the below call? which of the templates will be used and when?



Also why does the first template+class declaration is lacking "<S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?



#include <iostream>
#include <stdio.h>
using namespace std;


template<typename... S>
struct Example /* <S...> */ ;

template<typename H, typename... T>
struct Example<H, T...>

static const size_t value = sizeof(H) + Example<T...>::value;
;

template<>
struct Example<>

static const size_t value = 0;
;


int main()
cout << Example<long, int, char>::value << endl;
return 0;



Output: 13










share|improve this question









New contributor




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
























    7















    I'm trying to understand the below example, but I'm a bit confused from the three different template and struct declarations.



    Could you please describe what will happen for the below call? which of the templates will be used and when?



    Also why does the first template+class declaration is lacking "<S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?



    #include <iostream>
    #include <stdio.h>
    using namespace std;


    template<typename... S>
    struct Example /* <S...> */ ;

    template<typename H, typename... T>
    struct Example<H, T...>

    static const size_t value = sizeof(H) + Example<T...>::value;
    ;

    template<>
    struct Example<>

    static const size_t value = 0;
    ;


    int main()
    cout << Example<long, int, char>::value << endl;
    return 0;



    Output: 13










    share|improve this question









    New contributor




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






















      7












      7








      7


      1






      I'm trying to understand the below example, but I'm a bit confused from the three different template and struct declarations.



      Could you please describe what will happen for the below call? which of the templates will be used and when?



      Also why does the first template+class declaration is lacking "<S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?



      #include <iostream>
      #include <stdio.h>
      using namespace std;


      template<typename... S>
      struct Example /* <S...> */ ;

      template<typename H, typename... T>
      struct Example<H, T...>

      static const size_t value = sizeof(H) + Example<T...>::value;
      ;

      template<>
      struct Example<>

      static const size_t value = 0;
      ;


      int main()
      cout << Example<long, int, char>::value << endl;
      return 0;



      Output: 13










      share|improve this question









      New contributor




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












      I'm trying to understand the below example, but I'm a bit confused from the three different template and struct declarations.



      Could you please describe what will happen for the below call? which of the templates will be used and when?



      Also why does the first template+class declaration is lacking "<S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?



      #include <iostream>
      #include <stdio.h>
      using namespace std;


      template<typename... S>
      struct Example /* <S...> */ ;

      template<typename H, typename... T>
      struct Example<H, T...>

      static const size_t value = sizeof(H) + Example<T...>::value;
      ;

      template<>
      struct Example<>

      static const size_t value = 0;
      ;


      int main()
      cout << Example<long, int, char>::value << endl;
      return 0;



      Output: 13







      c++ c++11 templates variadic-templates template-specialization






      share|improve this question









      New contributor




      katkato 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




      katkato 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 4 hours ago









      max66

      37.7k74370




      37.7k74370






      New contributor




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









      asked 5 hours ago









      katkatokatkato

      362




      362




      New contributor




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





      New contributor





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






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






















          3 Answers
          3






          active

          oldest

          votes


















          4














          The first declares the template of a struct named Example, accepting any number of types:



          template<typename... S>
          struct Example /* <S...> */ ;


          If the name of the newly declared template was followed by <>, with or without arguments, it would be a specialization instead!



          The second defines a partial specialization for at least one type-argument:



          template<typename H, typename... T>
          struct Example<H, T...>

          static const size_t value = sizeof(H) + Example<T...>::value;
          ;


          And the last one defines a full specialization for no type-arguments:



          template<>
          struct Example<>

          static const size_t value = 0;
          ;


          Take note that template is followed by empty <>-brackets.



          It doesn't matter that the partial specialization is defined before the full specialization because instantiation must be deferred until the templates type-arguments are known.



          The specific instance you use, Example<long,int,char>::value, depends on Example<int, char>::value, which depends on Example<char>, which leads to the base-case:



          Example<long, int, char>::value = sizeof(long) + Example<int, char>::value; // sizeof(long) + sizeof(int) + 1 + 0
          Example<int, char>::value = sizeof(int) + Example<char>::value; // sizeof(int) + 1 + 0
          Example<char>::value = sizeof(char) + Example<>::value; // 1 + 0
          Example<>::value = 0;


          Of course, the example could be simplified:



          template <class... T>
          struct Example
          static const size_t value = 0;
          static_assert(!sizeof...(T), "The base-template only handles no template arguments.");
          ;
          template <class H, class... T>
          struct Example
          static const size_t value = sizeof(H) + Example<T...>::example;
          ;


          Or with C++17 fold-expressions:



          template <class... T>
          struct Example
          static const size_t value = 0 + ... + sizeof(T);
          ;


          As an aside, there are good reasons never to use using namespace std;, I wonder why you #include <stdio.h>, and return 0; is redundant for main().






          share|improve this answer

























          • In your simplified version, why does the base template only handle the empty case?

            – Apollys
            1 hour ago











          • Yes, it handles only the empty case, and that's because putting the base case into the base template generally works out for the best. One could use helper-macros to make it the other way around, but that gets messy.

            – Deduplicator
            1 hour ago


















          3














          Only answering this part of your question:




          Also why does the first template+class declaration is lacking < S...> right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?





          • When you declare a templated function/class/struct/type, you only use the angle bracket< > once, before the declaration:



            template <typename T> 
            void foo(T x);



          • When you declare a specific instantiation of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



            template <>
            void foo<int>(int& x);



          • When you declare a specific specialization of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



            template 
            void foo<int>(int& x);


          More on the last two items (and how they differ):



          Difference between instantiation and specialization in c++ templates






          share|improve this answer
































            1















            Also why does the first template+class declaration is lacking "< S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?




            It seems to me that is better to start from this point.



            First of all, the following (removed the <S...> commented) is a declaration (attention: declaration only, not definition) of a template struct Example that receive a variadic list of type template parameters



            template<typename... S>
            struct Example;


            You can also avoid to use the S and write simply



            template <typename...>
            struct Example;


            because the name of the variadic list isn't used in this context.



            At this point the compiler know that there is a variadic template struct Example but doesn't know how is made.



            Next we add the definition of a specialization of Example that receive one or more template parameter (observe that Example is defined to receive zero or more parameter, so a specialization that receive one or more parameter is special case of Example)



            //....... one --> V VVVVV <- or more template parameter
            template<typename H, typename... T>
            struct Example<H, T...>
            // .........^^^^^^^^^ <- this is a specialization
            static const size_t value = sizeof(H) + Example<T...>::value;
            ;


            The <H, T...> part after Example identifies a specialization (as said).



            This specialization define a static const size_t variable initialized with the sum of the sizeof(H) (the sizeof() of the first type template parameter) with the value defined in another Example class: Example<T...>.



            So you're observing a recursive definition: value is the sum of the sizeof() of the first parameter (a type) with the sum of the sizeof() of the following types.



            Suggestion: if you use variadic templates, you can use also constexpr, so better define value as constexpr



             static constexpr std::size_t value = sizeof(H) + Example<T...>::value;


            Or better, you can inherit from std::integral_constant



            template <typename H, typename... T>
            struct Example <H, T...>
            : public std::integral_constant<std::size_t, sizeof(H) + Example<T...>>
            ;


            so you inherit value from std::integral_constant with additional useful facilities (by example: automatic conversion to std::size_t in a context where a std::size_t is required)



            Every recursion needs a ground case, so you have



            template<>
            struct Example<>

            static const size_t value = 0;
            ;


            the declaration of another specialization of Example; this time the case with exactly zero template parameter (Example<>). In this case you have the definition of a value that is zero to terminate the recursion.



            As before, you can define value as constexpr or, better IMHO, using again std::integral_constant



            template <>
            struct Example<> : public std::integral_constant<std::size_t, 0u>
            ;


            Now you have defined two specializations for Example: one for the one-or-more parameters cases, one for the zero-parameters case. So you have covered all cases for Example that is declared receiving zero-or-more parameters; there is no needs to declare the generic (not specialized version) of Example.



            As observed by Deduplicator, you can define the generic case and only one specialization: if you write



            template <typename...>
            struct Example : public std::integral_constant<std::size_t, 0u>
            ;

            template <typename T, typename ... Ts>
            struct Example<T, Ts...>
            : public std::integral_constant<std::size_t, sizeof(T)+Example<Ts...>>
            ;


            you first declare Example receiving zero-or-more parameters and define the generic case with a value zero (the ground case), next you define a one-or-more specialization.



            Considering that the compiler select the more specialized version (when more version matches), the compiler select the specialization when there is one-or-more parameters (bot versions match but the specialization is more specialized) and the generic version when there are zero parameters (because the specialization doesn't matches).



            This way is a little more synthetic but can be less clear.




            Could you please describe what will happen for the below call? which of the templates will be used and when?




            Now should be simple to understand.



            When you write



            Example<long, int, char>::value


            you ask for the value of Example<long, int, char>.



            Three parameters, so the one-or-more specialization is selected, that is



            value = sizeof(long) + Example<int, char>::value;


            for the same reason, the value in Example<int, char> is



            value = sizeof(int) + Example<char>::value;


            and the value in Example<char> is



            value = sizeof(char) + Example<>::value;


            Now, for Example<>::value, the zero-parameters specialization is selected and Example<>::value is zero.



            Concluding, we have that value in Example<long, int, char> is initialized with



             value = sizeof(long) + sizeof(int) + sizeof(char) + 0;


            You tagged C++11, so it's a pity you can't use C++17 (template folding) where you can avoid recursion at all and define Example as a using



            template <typename ... Ts>
            using Example = std::integral_constant<std::size_t, (... + sizeof(Ts))>;





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



              );






              katkato 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%2f55109599%2fdeclaring-and-defining-template-and-specialising-them%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              4














              The first declares the template of a struct named Example, accepting any number of types:



              template<typename... S>
              struct Example /* <S...> */ ;


              If the name of the newly declared template was followed by <>, with or without arguments, it would be a specialization instead!



              The second defines a partial specialization for at least one type-argument:



              template<typename H, typename... T>
              struct Example<H, T...>

              static const size_t value = sizeof(H) + Example<T...>::value;
              ;


              And the last one defines a full specialization for no type-arguments:



              template<>
              struct Example<>

              static const size_t value = 0;
              ;


              Take note that template is followed by empty <>-brackets.



              It doesn't matter that the partial specialization is defined before the full specialization because instantiation must be deferred until the templates type-arguments are known.



              The specific instance you use, Example<long,int,char>::value, depends on Example<int, char>::value, which depends on Example<char>, which leads to the base-case:



              Example<long, int, char>::value = sizeof(long) + Example<int, char>::value; // sizeof(long) + sizeof(int) + 1 + 0
              Example<int, char>::value = sizeof(int) + Example<char>::value; // sizeof(int) + 1 + 0
              Example<char>::value = sizeof(char) + Example<>::value; // 1 + 0
              Example<>::value = 0;


              Of course, the example could be simplified:



              template <class... T>
              struct Example
              static const size_t value = 0;
              static_assert(!sizeof...(T), "The base-template only handles no template arguments.");
              ;
              template <class H, class... T>
              struct Example
              static const size_t value = sizeof(H) + Example<T...>::example;
              ;


              Or with C++17 fold-expressions:



              template <class... T>
              struct Example
              static const size_t value = 0 + ... + sizeof(T);
              ;


              As an aside, there are good reasons never to use using namespace std;, I wonder why you #include <stdio.h>, and return 0; is redundant for main().






              share|improve this answer

























              • In your simplified version, why does the base template only handle the empty case?

                – Apollys
                1 hour ago











              • Yes, it handles only the empty case, and that's because putting the base case into the base template generally works out for the best. One could use helper-macros to make it the other way around, but that gets messy.

                – Deduplicator
                1 hour ago















              4














              The first declares the template of a struct named Example, accepting any number of types:



              template<typename... S>
              struct Example /* <S...> */ ;


              If the name of the newly declared template was followed by <>, with or without arguments, it would be a specialization instead!



              The second defines a partial specialization for at least one type-argument:



              template<typename H, typename... T>
              struct Example<H, T...>

              static const size_t value = sizeof(H) + Example<T...>::value;
              ;


              And the last one defines a full specialization for no type-arguments:



              template<>
              struct Example<>

              static const size_t value = 0;
              ;


              Take note that template is followed by empty <>-brackets.



              It doesn't matter that the partial specialization is defined before the full specialization because instantiation must be deferred until the templates type-arguments are known.



              The specific instance you use, Example<long,int,char>::value, depends on Example<int, char>::value, which depends on Example<char>, which leads to the base-case:



              Example<long, int, char>::value = sizeof(long) + Example<int, char>::value; // sizeof(long) + sizeof(int) + 1 + 0
              Example<int, char>::value = sizeof(int) + Example<char>::value; // sizeof(int) + 1 + 0
              Example<char>::value = sizeof(char) + Example<>::value; // 1 + 0
              Example<>::value = 0;


              Of course, the example could be simplified:



              template <class... T>
              struct Example
              static const size_t value = 0;
              static_assert(!sizeof...(T), "The base-template only handles no template arguments.");
              ;
              template <class H, class... T>
              struct Example
              static const size_t value = sizeof(H) + Example<T...>::example;
              ;


              Or with C++17 fold-expressions:



              template <class... T>
              struct Example
              static const size_t value = 0 + ... + sizeof(T);
              ;


              As an aside, there are good reasons never to use using namespace std;, I wonder why you #include <stdio.h>, and return 0; is redundant for main().






              share|improve this answer

























              • In your simplified version, why does the base template only handle the empty case?

                – Apollys
                1 hour ago











              • Yes, it handles only the empty case, and that's because putting the base case into the base template generally works out for the best. One could use helper-macros to make it the other way around, but that gets messy.

                – Deduplicator
                1 hour ago













              4












              4








              4







              The first declares the template of a struct named Example, accepting any number of types:



              template<typename... S>
              struct Example /* <S...> */ ;


              If the name of the newly declared template was followed by <>, with or without arguments, it would be a specialization instead!



              The second defines a partial specialization for at least one type-argument:



              template<typename H, typename... T>
              struct Example<H, T...>

              static const size_t value = sizeof(H) + Example<T...>::value;
              ;


              And the last one defines a full specialization for no type-arguments:



              template<>
              struct Example<>

              static const size_t value = 0;
              ;


              Take note that template is followed by empty <>-brackets.



              It doesn't matter that the partial specialization is defined before the full specialization because instantiation must be deferred until the templates type-arguments are known.



              The specific instance you use, Example<long,int,char>::value, depends on Example<int, char>::value, which depends on Example<char>, which leads to the base-case:



              Example<long, int, char>::value = sizeof(long) + Example<int, char>::value; // sizeof(long) + sizeof(int) + 1 + 0
              Example<int, char>::value = sizeof(int) + Example<char>::value; // sizeof(int) + 1 + 0
              Example<char>::value = sizeof(char) + Example<>::value; // 1 + 0
              Example<>::value = 0;


              Of course, the example could be simplified:



              template <class... T>
              struct Example
              static const size_t value = 0;
              static_assert(!sizeof...(T), "The base-template only handles no template arguments.");
              ;
              template <class H, class... T>
              struct Example
              static const size_t value = sizeof(H) + Example<T...>::example;
              ;


              Or with C++17 fold-expressions:



              template <class... T>
              struct Example
              static const size_t value = 0 + ... + sizeof(T);
              ;


              As an aside, there are good reasons never to use using namespace std;, I wonder why you #include <stdio.h>, and return 0; is redundant for main().






              share|improve this answer















              The first declares the template of a struct named Example, accepting any number of types:



              template<typename... S>
              struct Example /* <S...> */ ;


              If the name of the newly declared template was followed by <>, with or without arguments, it would be a specialization instead!



              The second defines a partial specialization for at least one type-argument:



              template<typename H, typename... T>
              struct Example<H, T...>

              static const size_t value = sizeof(H) + Example<T...>::value;
              ;


              And the last one defines a full specialization for no type-arguments:



              template<>
              struct Example<>

              static const size_t value = 0;
              ;


              Take note that template is followed by empty <>-brackets.



              It doesn't matter that the partial specialization is defined before the full specialization because instantiation must be deferred until the templates type-arguments are known.



              The specific instance you use, Example<long,int,char>::value, depends on Example<int, char>::value, which depends on Example<char>, which leads to the base-case:



              Example<long, int, char>::value = sizeof(long) + Example<int, char>::value; // sizeof(long) + sizeof(int) + 1 + 0
              Example<int, char>::value = sizeof(int) + Example<char>::value; // sizeof(int) + 1 + 0
              Example<char>::value = sizeof(char) + Example<>::value; // 1 + 0
              Example<>::value = 0;


              Of course, the example could be simplified:



              template <class... T>
              struct Example
              static const size_t value = 0;
              static_assert(!sizeof...(T), "The base-template only handles no template arguments.");
              ;
              template <class H, class... T>
              struct Example
              static const size_t value = sizeof(H) + Example<T...>::example;
              ;


              Or with C++17 fold-expressions:



              template <class... T>
              struct Example
              static const size_t value = 0 + ... + sizeof(T);
              ;


              As an aside, there are good reasons never to use using namespace std;, I wonder why you #include <stdio.h>, and return 0; is redundant for main().







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 3 hours ago









              alter igel

              2,76811027




              2,76811027










              answered 4 hours ago









              DeduplicatorDeduplicator

              34.7k64990




              34.7k64990












              • In your simplified version, why does the base template only handle the empty case?

                – Apollys
                1 hour ago











              • Yes, it handles only the empty case, and that's because putting the base case into the base template generally works out for the best. One could use helper-macros to make it the other way around, but that gets messy.

                – Deduplicator
                1 hour ago

















              • In your simplified version, why does the base template only handle the empty case?

                – Apollys
                1 hour ago











              • Yes, it handles only the empty case, and that's because putting the base case into the base template generally works out for the best. One could use helper-macros to make it the other way around, but that gets messy.

                – Deduplicator
                1 hour ago
















              In your simplified version, why does the base template only handle the empty case?

              – Apollys
              1 hour ago





              In your simplified version, why does the base template only handle the empty case?

              – Apollys
              1 hour ago













              Yes, it handles only the empty case, and that's because putting the base case into the base template generally works out for the best. One could use helper-macros to make it the other way around, but that gets messy.

              – Deduplicator
              1 hour ago





              Yes, it handles only the empty case, and that's because putting the base case into the base template generally works out for the best. One could use helper-macros to make it the other way around, but that gets messy.

              – Deduplicator
              1 hour ago













              3














              Only answering this part of your question:




              Also why does the first template+class declaration is lacking < S...> right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?





              • When you declare a templated function/class/struct/type, you only use the angle bracket< > once, before the declaration:



                template <typename T> 
                void foo(T x);



              • When you declare a specific instantiation of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                template <>
                void foo<int>(int& x);



              • When you declare a specific specialization of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                template 
                void foo<int>(int& x);


              More on the last two items (and how they differ):



              Difference between instantiation and specialization in c++ templates






              share|improve this answer





























                3














                Only answering this part of your question:




                Also why does the first template+class declaration is lacking < S...> right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?





                • When you declare a templated function/class/struct/type, you only use the angle bracket< > once, before the declaration:



                  template <typename T> 
                  void foo(T x);



                • When you declare a specific instantiation of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                  template <>
                  void foo<int>(int& x);



                • When you declare a specific specialization of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                  template 
                  void foo<int>(int& x);


                More on the last two items (and how they differ):



                Difference between instantiation and specialization in c++ templates






                share|improve this answer



























                  3












                  3








                  3







                  Only answering this part of your question:




                  Also why does the first template+class declaration is lacking < S...> right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?





                  • When you declare a templated function/class/struct/type, you only use the angle bracket< > once, before the declaration:



                    template <typename T> 
                    void foo(T x);



                  • When you declare a specific instantiation of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                    template <>
                    void foo<int>(int& x);



                  • When you declare a specific specialization of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                    template 
                    void foo<int>(int& x);


                  More on the last two items (and how they differ):



                  Difference between instantiation and specialization in c++ templates






                  share|improve this answer















                  Only answering this part of your question:




                  Also why does the first template+class declaration is lacking < S...> right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?





                  • When you declare a templated function/class/struct/type, you only use the angle bracket< > once, before the declaration:



                    template <typename T> 
                    void foo(T x);



                  • When you declare a specific instantiation of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                    template <>
                    void foo<int>(int& x);



                  • When you declare a specific specialization of the general template, you use < > twice, once empty before the declaration, then again with the specific template parameters for which you're instantating:



                    template 
                    void foo<int>(int& x);


                  More on the last two items (and how they differ):



                  Difference between instantiation and specialization in c++ templates







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 4 hours ago

























                  answered 4 hours ago









                  einpoklumeinpoklum

                  35.4k27129254




                  35.4k27129254





















                      1















                      Also why does the first template+class declaration is lacking "< S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?




                      It seems to me that is better to start from this point.



                      First of all, the following (removed the <S...> commented) is a declaration (attention: declaration only, not definition) of a template struct Example that receive a variadic list of type template parameters



                      template<typename... S>
                      struct Example;


                      You can also avoid to use the S and write simply



                      template <typename...>
                      struct Example;


                      because the name of the variadic list isn't used in this context.



                      At this point the compiler know that there is a variadic template struct Example but doesn't know how is made.



                      Next we add the definition of a specialization of Example that receive one or more template parameter (observe that Example is defined to receive zero or more parameter, so a specialization that receive one or more parameter is special case of Example)



                      //....... one --> V VVVVV <- or more template parameter
                      template<typename H, typename... T>
                      struct Example<H, T...>
                      // .........^^^^^^^^^ <- this is a specialization
                      static const size_t value = sizeof(H) + Example<T...>::value;
                      ;


                      The <H, T...> part after Example identifies a specialization (as said).



                      This specialization define a static const size_t variable initialized with the sum of the sizeof(H) (the sizeof() of the first type template parameter) with the value defined in another Example class: Example<T...>.



                      So you're observing a recursive definition: value is the sum of the sizeof() of the first parameter (a type) with the sum of the sizeof() of the following types.



                      Suggestion: if you use variadic templates, you can use also constexpr, so better define value as constexpr



                       static constexpr std::size_t value = sizeof(H) + Example<T...>::value;


                      Or better, you can inherit from std::integral_constant



                      template <typename H, typename... T>
                      struct Example <H, T...>
                      : public std::integral_constant<std::size_t, sizeof(H) + Example<T...>>
                      ;


                      so you inherit value from std::integral_constant with additional useful facilities (by example: automatic conversion to std::size_t in a context where a std::size_t is required)



                      Every recursion needs a ground case, so you have



                      template<>
                      struct Example<>

                      static const size_t value = 0;
                      ;


                      the declaration of another specialization of Example; this time the case with exactly zero template parameter (Example<>). In this case you have the definition of a value that is zero to terminate the recursion.



                      As before, you can define value as constexpr or, better IMHO, using again std::integral_constant



                      template <>
                      struct Example<> : public std::integral_constant<std::size_t, 0u>
                      ;


                      Now you have defined two specializations for Example: one for the one-or-more parameters cases, one for the zero-parameters case. So you have covered all cases for Example that is declared receiving zero-or-more parameters; there is no needs to declare the generic (not specialized version) of Example.



                      As observed by Deduplicator, you can define the generic case and only one specialization: if you write



                      template <typename...>
                      struct Example : public std::integral_constant<std::size_t, 0u>
                      ;

                      template <typename T, typename ... Ts>
                      struct Example<T, Ts...>
                      : public std::integral_constant<std::size_t, sizeof(T)+Example<Ts...>>
                      ;


                      you first declare Example receiving zero-or-more parameters and define the generic case with a value zero (the ground case), next you define a one-or-more specialization.



                      Considering that the compiler select the more specialized version (when more version matches), the compiler select the specialization when there is one-or-more parameters (bot versions match but the specialization is more specialized) and the generic version when there are zero parameters (because the specialization doesn't matches).



                      This way is a little more synthetic but can be less clear.




                      Could you please describe what will happen for the below call? which of the templates will be used and when?




                      Now should be simple to understand.



                      When you write



                      Example<long, int, char>::value


                      you ask for the value of Example<long, int, char>.



                      Three parameters, so the one-or-more specialization is selected, that is



                      value = sizeof(long) + Example<int, char>::value;


                      for the same reason, the value in Example<int, char> is



                      value = sizeof(int) + Example<char>::value;


                      and the value in Example<char> is



                      value = sizeof(char) + Example<>::value;


                      Now, for Example<>::value, the zero-parameters specialization is selected and Example<>::value is zero.



                      Concluding, we have that value in Example<long, int, char> is initialized with



                       value = sizeof(long) + sizeof(int) + sizeof(char) + 0;


                      You tagged C++11, so it's a pity you can't use C++17 (template folding) where you can avoid recursion at all and define Example as a using



                      template <typename ... Ts>
                      using Example = std::integral_constant<std::size_t, (... + sizeof(Ts))>;





                      share|improve this answer





























                        1















                        Also why does the first template+class declaration is lacking "< S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?




                        It seems to me that is better to start from this point.



                        First of all, the following (removed the <S...> commented) is a declaration (attention: declaration only, not definition) of a template struct Example that receive a variadic list of type template parameters



                        template<typename... S>
                        struct Example;


                        You can also avoid to use the S and write simply



                        template <typename...>
                        struct Example;


                        because the name of the variadic list isn't used in this context.



                        At this point the compiler know that there is a variadic template struct Example but doesn't know how is made.



                        Next we add the definition of a specialization of Example that receive one or more template parameter (observe that Example is defined to receive zero or more parameter, so a specialization that receive one or more parameter is special case of Example)



                        //....... one --> V VVVVV <- or more template parameter
                        template<typename H, typename... T>
                        struct Example<H, T...>
                        // .........^^^^^^^^^ <- this is a specialization
                        static const size_t value = sizeof(H) + Example<T...>::value;
                        ;


                        The <H, T...> part after Example identifies a specialization (as said).



                        This specialization define a static const size_t variable initialized with the sum of the sizeof(H) (the sizeof() of the first type template parameter) with the value defined in another Example class: Example<T...>.



                        So you're observing a recursive definition: value is the sum of the sizeof() of the first parameter (a type) with the sum of the sizeof() of the following types.



                        Suggestion: if you use variadic templates, you can use also constexpr, so better define value as constexpr



                         static constexpr std::size_t value = sizeof(H) + Example<T...>::value;


                        Or better, you can inherit from std::integral_constant



                        template <typename H, typename... T>
                        struct Example <H, T...>
                        : public std::integral_constant<std::size_t, sizeof(H) + Example<T...>>
                        ;


                        so you inherit value from std::integral_constant with additional useful facilities (by example: automatic conversion to std::size_t in a context where a std::size_t is required)



                        Every recursion needs a ground case, so you have



                        template<>
                        struct Example<>

                        static const size_t value = 0;
                        ;


                        the declaration of another specialization of Example; this time the case with exactly zero template parameter (Example<>). In this case you have the definition of a value that is zero to terminate the recursion.



                        As before, you can define value as constexpr or, better IMHO, using again std::integral_constant



                        template <>
                        struct Example<> : public std::integral_constant<std::size_t, 0u>
                        ;


                        Now you have defined two specializations for Example: one for the one-or-more parameters cases, one for the zero-parameters case. So you have covered all cases for Example that is declared receiving zero-or-more parameters; there is no needs to declare the generic (not specialized version) of Example.



                        As observed by Deduplicator, you can define the generic case and only one specialization: if you write



                        template <typename...>
                        struct Example : public std::integral_constant<std::size_t, 0u>
                        ;

                        template <typename T, typename ... Ts>
                        struct Example<T, Ts...>
                        : public std::integral_constant<std::size_t, sizeof(T)+Example<Ts...>>
                        ;


                        you first declare Example receiving zero-or-more parameters and define the generic case with a value zero (the ground case), next you define a one-or-more specialization.



                        Considering that the compiler select the more specialized version (when more version matches), the compiler select the specialization when there is one-or-more parameters (bot versions match but the specialization is more specialized) and the generic version when there are zero parameters (because the specialization doesn't matches).



                        This way is a little more synthetic but can be less clear.




                        Could you please describe what will happen for the below call? which of the templates will be used and when?




                        Now should be simple to understand.



                        When you write



                        Example<long, int, char>::value


                        you ask for the value of Example<long, int, char>.



                        Three parameters, so the one-or-more specialization is selected, that is



                        value = sizeof(long) + Example<int, char>::value;


                        for the same reason, the value in Example<int, char> is



                        value = sizeof(int) + Example<char>::value;


                        and the value in Example<char> is



                        value = sizeof(char) + Example<>::value;


                        Now, for Example<>::value, the zero-parameters specialization is selected and Example<>::value is zero.



                        Concluding, we have that value in Example<long, int, char> is initialized with



                         value = sizeof(long) + sizeof(int) + sizeof(char) + 0;


                        You tagged C++11, so it's a pity you can't use C++17 (template folding) where you can avoid recursion at all and define Example as a using



                        template <typename ... Ts>
                        using Example = std::integral_constant<std::size_t, (... + sizeof(Ts))>;





                        share|improve this answer



























                          1












                          1








                          1








                          Also why does the first template+class declaration is lacking "< S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?




                          It seems to me that is better to start from this point.



                          First of all, the following (removed the <S...> commented) is a declaration (attention: declaration only, not definition) of a template struct Example that receive a variadic list of type template parameters



                          template<typename... S>
                          struct Example;


                          You can also avoid to use the S and write simply



                          template <typename...>
                          struct Example;


                          because the name of the variadic list isn't used in this context.



                          At this point the compiler know that there is a variadic template struct Example but doesn't know how is made.



                          Next we add the definition of a specialization of Example that receive one or more template parameter (observe that Example is defined to receive zero or more parameter, so a specialization that receive one or more parameter is special case of Example)



                          //....... one --> V VVVVV <- or more template parameter
                          template<typename H, typename... T>
                          struct Example<H, T...>
                          // .........^^^^^^^^^ <- this is a specialization
                          static const size_t value = sizeof(H) + Example<T...>::value;
                          ;


                          The <H, T...> part after Example identifies a specialization (as said).



                          This specialization define a static const size_t variable initialized with the sum of the sizeof(H) (the sizeof() of the first type template parameter) with the value defined in another Example class: Example<T...>.



                          So you're observing a recursive definition: value is the sum of the sizeof() of the first parameter (a type) with the sum of the sizeof() of the following types.



                          Suggestion: if you use variadic templates, you can use also constexpr, so better define value as constexpr



                           static constexpr std::size_t value = sizeof(H) + Example<T...>::value;


                          Or better, you can inherit from std::integral_constant



                          template <typename H, typename... T>
                          struct Example <H, T...>
                          : public std::integral_constant<std::size_t, sizeof(H) + Example<T...>>
                          ;


                          so you inherit value from std::integral_constant with additional useful facilities (by example: automatic conversion to std::size_t in a context where a std::size_t is required)



                          Every recursion needs a ground case, so you have



                          template<>
                          struct Example<>

                          static const size_t value = 0;
                          ;


                          the declaration of another specialization of Example; this time the case with exactly zero template parameter (Example<>). In this case you have the definition of a value that is zero to terminate the recursion.



                          As before, you can define value as constexpr or, better IMHO, using again std::integral_constant



                          template <>
                          struct Example<> : public std::integral_constant<std::size_t, 0u>
                          ;


                          Now you have defined two specializations for Example: one for the one-or-more parameters cases, one for the zero-parameters case. So you have covered all cases for Example that is declared receiving zero-or-more parameters; there is no needs to declare the generic (not specialized version) of Example.



                          As observed by Deduplicator, you can define the generic case and only one specialization: if you write



                          template <typename...>
                          struct Example : public std::integral_constant<std::size_t, 0u>
                          ;

                          template <typename T, typename ... Ts>
                          struct Example<T, Ts...>
                          : public std::integral_constant<std::size_t, sizeof(T)+Example<Ts...>>
                          ;


                          you first declare Example receiving zero-or-more parameters and define the generic case with a value zero (the ground case), next you define a one-or-more specialization.



                          Considering that the compiler select the more specialized version (when more version matches), the compiler select the specialization when there is one-or-more parameters (bot versions match but the specialization is more specialized) and the generic version when there are zero parameters (because the specialization doesn't matches).



                          This way is a little more synthetic but can be less clear.




                          Could you please describe what will happen for the below call? which of the templates will be used and when?




                          Now should be simple to understand.



                          When you write



                          Example<long, int, char>::value


                          you ask for the value of Example<long, int, char>.



                          Three parameters, so the one-or-more specialization is selected, that is



                          value = sizeof(long) + Example<int, char>::value;


                          for the same reason, the value in Example<int, char> is



                          value = sizeof(int) + Example<char>::value;


                          and the value in Example<char> is



                          value = sizeof(char) + Example<>::value;


                          Now, for Example<>::value, the zero-parameters specialization is selected and Example<>::value is zero.



                          Concluding, we have that value in Example<long, int, char> is initialized with



                           value = sizeof(long) + sizeof(int) + sizeof(char) + 0;


                          You tagged C++11, so it's a pity you can't use C++17 (template folding) where you can avoid recursion at all and define Example as a using



                          template <typename ... Ts>
                          using Example = std::integral_constant<std::size_t, (... + sizeof(Ts))>;





                          share|improve this answer
















                          Also why does the first template+class declaration is lacking "< S...>" right after the struct declaration?(see what's commented out)? when it's right to add it and when it's not?




                          It seems to me that is better to start from this point.



                          First of all, the following (removed the <S...> commented) is a declaration (attention: declaration only, not definition) of a template struct Example that receive a variadic list of type template parameters



                          template<typename... S>
                          struct Example;


                          You can also avoid to use the S and write simply



                          template <typename...>
                          struct Example;


                          because the name of the variadic list isn't used in this context.



                          At this point the compiler know that there is a variadic template struct Example but doesn't know how is made.



                          Next we add the definition of a specialization of Example that receive one or more template parameter (observe that Example is defined to receive zero or more parameter, so a specialization that receive one or more parameter is special case of Example)



                          //....... one --> V VVVVV <- or more template parameter
                          template<typename H, typename... T>
                          struct Example<H, T...>
                          // .........^^^^^^^^^ <- this is a specialization
                          static const size_t value = sizeof(H) + Example<T...>::value;
                          ;


                          The <H, T...> part after Example identifies a specialization (as said).



                          This specialization define a static const size_t variable initialized with the sum of the sizeof(H) (the sizeof() of the first type template parameter) with the value defined in another Example class: Example<T...>.



                          So you're observing a recursive definition: value is the sum of the sizeof() of the first parameter (a type) with the sum of the sizeof() of the following types.



                          Suggestion: if you use variadic templates, you can use also constexpr, so better define value as constexpr



                           static constexpr std::size_t value = sizeof(H) + Example<T...>::value;


                          Or better, you can inherit from std::integral_constant



                          template <typename H, typename... T>
                          struct Example <H, T...>
                          : public std::integral_constant<std::size_t, sizeof(H) + Example<T...>>
                          ;


                          so you inherit value from std::integral_constant with additional useful facilities (by example: automatic conversion to std::size_t in a context where a std::size_t is required)



                          Every recursion needs a ground case, so you have



                          template<>
                          struct Example<>

                          static const size_t value = 0;
                          ;


                          the declaration of another specialization of Example; this time the case with exactly zero template parameter (Example<>). In this case you have the definition of a value that is zero to terminate the recursion.



                          As before, you can define value as constexpr or, better IMHO, using again std::integral_constant



                          template <>
                          struct Example<> : public std::integral_constant<std::size_t, 0u>
                          ;


                          Now you have defined two specializations for Example: one for the one-or-more parameters cases, one for the zero-parameters case. So you have covered all cases for Example that is declared receiving zero-or-more parameters; there is no needs to declare the generic (not specialized version) of Example.



                          As observed by Deduplicator, you can define the generic case and only one specialization: if you write



                          template <typename...>
                          struct Example : public std::integral_constant<std::size_t, 0u>
                          ;

                          template <typename T, typename ... Ts>
                          struct Example<T, Ts...>
                          : public std::integral_constant<std::size_t, sizeof(T)+Example<Ts...>>
                          ;


                          you first declare Example receiving zero-or-more parameters and define the generic case with a value zero (the ground case), next you define a one-or-more specialization.



                          Considering that the compiler select the more specialized version (when more version matches), the compiler select the specialization when there is one-or-more parameters (bot versions match but the specialization is more specialized) and the generic version when there are zero parameters (because the specialization doesn't matches).



                          This way is a little more synthetic but can be less clear.




                          Could you please describe what will happen for the below call? which of the templates will be used and when?




                          Now should be simple to understand.



                          When you write



                          Example<long, int, char>::value


                          you ask for the value of Example<long, int, char>.



                          Three parameters, so the one-or-more specialization is selected, that is



                          value = sizeof(long) + Example<int, char>::value;


                          for the same reason, the value in Example<int, char> is



                          value = sizeof(int) + Example<char>::value;


                          and the value in Example<char> is



                          value = sizeof(char) + Example<>::value;


                          Now, for Example<>::value, the zero-parameters specialization is selected and Example<>::value is zero.



                          Concluding, we have that value in Example<long, int, char> is initialized with



                           value = sizeof(long) + sizeof(int) + sizeof(char) + 0;


                          You tagged C++11, so it's a pity you can't use C++17 (template folding) where you can avoid recursion at all and define Example as a using



                          template <typename ... Ts>
                          using Example = std::integral_constant<std::size_t, (... + sizeof(Ts))>;






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited 3 hours ago

























                          answered 4 hours ago









                          max66max66

                          37.7k74370




                          37.7k74370




















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









                              draft saved

                              draft discarded


















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












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











                              katkato 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%2f55109599%2fdeclaring-and-defining-template-and-specialising-them%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







                              -c++, c++11, template-specialization, templates, variadic-templates

                              Popular posts from this blog

                              Frič See also Navigation menuinternal link

                              Identify plant with long narrow paired leaves and reddish stems Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?What is this plant with long sharp leaves? Is it a weed?What is this 3ft high, stalky plant, with mid sized narrow leaves?What is this young shrub with opposite ovate, crenate leaves and reddish stems?What is this plant with large broad serrated leaves?Identify this upright branching weed with long leaves and reddish stemsPlease help me identify this bulbous plant with long, broad leaves and white flowersWhat is this small annual with narrow gray/green leaves and rust colored daisy-type flowers?What is this chilli plant?Does anyone know what type of chilli plant this is?Help identify this plant

                              fontconfig warning: “/etc/fonts/fonts.conf”, line 100: unknown “element blank” The 2019 Stack Overflow Developer Survey Results Are In“tar: unrecognized option --warning” during 'apt-get install'How to fix Fontconfig errorHow do I figure out which font file is chosen for a system generic font alias?Why are some apt-get-installed fonts being ignored by fc-list, xfontsel, etc?Reload settings in /etc/fonts/conf.dTaking 30 seconds longer to boot after upgrade from jessie to stretchHow to match multiple font names with a single <match> element?Adding a custom font to fontconfigRemoving fonts from fontconfig <match> resultsBroken fonts after upgrading Firefox ESR to latest Firefox