Partial specialization does not use any of its template parameters












3















I'm trying to implement tuples with template metaprogramming, but am having problems with the indexing function get. The implementation of Tuple type is this:



template<typename A, typename... B>
class Tuple : Tuple<B...> {
private:
A val;
public:
using Base = Tuple<B...>;
Base* base() {
return static_cast<Base*>(this);
}
const Base* base() const {
return static_cast<const Base*>(this);
}
Tuple(A a, B... b): Base(b...), val(a) { }
A first() {
return val;
}
};

template<class A>
class Tuple<A> {
private:
A val;
public:
Tuple(A a): val{a} {}
A first() {
return val;
}
};


The implementation of get structure is:



template<int N, class... A>
struct get {
select<N,A...> operator()(Tuple<A...> t) {
return get<N-1>()(t.base());
}
};

template<class R, class... A>
struct get<0> {
R operator()(Tuple<R, A...> t) {
return t.first();
}
};


This is the error compiler is giving me:



tuple.cpp:53:8: error: partial specialization of 'get' does not use any of its template parameters
struct get<0> {
^
1 error generated.


Why am I getting this error? How can I correct it?



Note: select<N,A...> is a type function which selects type at Nth index from A.










share|improve this question

























  • I think you can resolve it if you simply change template <class R, class ... A> to template <> and change Tuple<R, A...> to Tuple<0>.

    – Nir Friedman
    Mar 16 '18 at 19:59
















3















I'm trying to implement tuples with template metaprogramming, but am having problems with the indexing function get. The implementation of Tuple type is this:



template<typename A, typename... B>
class Tuple : Tuple<B...> {
private:
A val;
public:
using Base = Tuple<B...>;
Base* base() {
return static_cast<Base*>(this);
}
const Base* base() const {
return static_cast<const Base*>(this);
}
Tuple(A a, B... b): Base(b...), val(a) { }
A first() {
return val;
}
};

template<class A>
class Tuple<A> {
private:
A val;
public:
Tuple(A a): val{a} {}
A first() {
return val;
}
};


The implementation of get structure is:



template<int N, class... A>
struct get {
select<N,A...> operator()(Tuple<A...> t) {
return get<N-1>()(t.base());
}
};

template<class R, class... A>
struct get<0> {
R operator()(Tuple<R, A...> t) {
return t.first();
}
};


This is the error compiler is giving me:



tuple.cpp:53:8: error: partial specialization of 'get' does not use any of its template parameters
struct get<0> {
^
1 error generated.


Why am I getting this error? How can I correct it?



Note: select<N,A...> is a type function which selects type at Nth index from A.










share|improve this question

























  • I think you can resolve it if you simply change template <class R, class ... A> to template <> and change Tuple<R, A...> to Tuple<0>.

    – Nir Friedman
    Mar 16 '18 at 19:59














3












3








3








I'm trying to implement tuples with template metaprogramming, but am having problems with the indexing function get. The implementation of Tuple type is this:



template<typename A, typename... B>
class Tuple : Tuple<B...> {
private:
A val;
public:
using Base = Tuple<B...>;
Base* base() {
return static_cast<Base*>(this);
}
const Base* base() const {
return static_cast<const Base*>(this);
}
Tuple(A a, B... b): Base(b...), val(a) { }
A first() {
return val;
}
};

template<class A>
class Tuple<A> {
private:
A val;
public:
Tuple(A a): val{a} {}
A first() {
return val;
}
};


The implementation of get structure is:



template<int N, class... A>
struct get {
select<N,A...> operator()(Tuple<A...> t) {
return get<N-1>()(t.base());
}
};

template<class R, class... A>
struct get<0> {
R operator()(Tuple<R, A...> t) {
return t.first();
}
};


This is the error compiler is giving me:



tuple.cpp:53:8: error: partial specialization of 'get' does not use any of its template parameters
struct get<0> {
^
1 error generated.


Why am I getting this error? How can I correct it?



Note: select<N,A...> is a type function which selects type at Nth index from A.










share|improve this question
















I'm trying to implement tuples with template metaprogramming, but am having problems with the indexing function get. The implementation of Tuple type is this:



template<typename A, typename... B>
class Tuple : Tuple<B...> {
private:
A val;
public:
using Base = Tuple<B...>;
Base* base() {
return static_cast<Base*>(this);
}
const Base* base() const {
return static_cast<const Base*>(this);
}
Tuple(A a, B... b): Base(b...), val(a) { }
A first() {
return val;
}
};

template<class A>
class Tuple<A> {
private:
A val;
public:
Tuple(A a): val{a} {}
A first() {
return val;
}
};


The implementation of get structure is:



template<int N, class... A>
struct get {
select<N,A...> operator()(Tuple<A...> t) {
return get<N-1>()(t.base());
}
};

template<class R, class... A>
struct get<0> {
R operator()(Tuple<R, A...> t) {
return t.first();
}
};


This is the error compiler is giving me:



tuple.cpp:53:8: error: partial specialization of 'get' does not use any of its template parameters
struct get<0> {
^
1 error generated.


Why am I getting this error? How can I correct it?



Note: select<N,A...> is a type function which selects type at Nth index from A.







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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 14:02









max66

35.1k73763




35.1k73763










asked Mar 16 '18 at 19:41









sagasaga

513315




513315













  • I think you can resolve it if you simply change template <class R, class ... A> to template <> and change Tuple<R, A...> to Tuple<0>.

    – Nir Friedman
    Mar 16 '18 at 19:59



















  • I think you can resolve it if you simply change template <class R, class ... A> to template <> and change Tuple<R, A...> to Tuple<0>.

    – Nir Friedman
    Mar 16 '18 at 19:59

















I think you can resolve it if you simply change template <class R, class ... A> to template <> and change Tuple<R, A...> to Tuple<0>.

– Nir Friedman
Mar 16 '18 at 19:59





I think you can resolve it if you simply change template <class R, class ... A> to template <> and change Tuple<R, A...> to Tuple<0>.

– Nir Friedman
Mar 16 '18 at 19:59












2 Answers
2






active

oldest

votes


















1














Your get's primary template is:



template<int N, class... A>
struct get{ ... };


your get's partial specialization is:



template<class R, class... A>
struct get<0>{ ... };


The specialization is receiving a single template argument, i.e.: 0, but the primary template above takes two template parameters:




  • the non-type template parameter N.

  • the variadic type parameter A.


Besides, how can R be deduced?





Specializing get instead as:



template<class R, class... A>
struct get<0, R, A...>{ ... };


will make possible R to be deduced: it will be deduced to the type of the first element of the passed variadic argument. For example, in:



get<0, int, float, double> foo;


R will be deduced to int.






share|improve this answer

































    1














    Maybe you have to partial specialize get as follows



    template<class R, class... A>
    struct get<0, R, A...> {
    R operator()(Tuple<R, A...> t) {
    return t.first();
    }
    };


    I mean... get<0, R, A...>, not get<0>



    But you have also to modify the main get to call the following call with the correct type list, so



    template<int N, typename A0, typename ... As>
    struct get {
    auto operator()(Tuple<A0, As...> t) {
    return get<N-1, As...>()(t.base());
    }
    };


    Otherwise you can also demand the types management to a template version of the operator() and maintain only the int N value for get



    template <int N>
    struct get
    {
    template <typename Tpl>
    auto operator() (Tpl t)
    -> decltype( get<N-1>()(t.base()) )
    { return get<N-1>()(t.base()); }
    };

    template<>
    struct get<0>
    {
    template <typename Tpl>
    auto operator() (Tpl t)
    -> decltype ( t.first() )
    { return t.first(); }
    };


    Starting from C++14 you can avoid the decltype() part.



    Off topic suggestion: avoid the use of names that can collide with std namespace names.



    Maybe myGet and myTuple instead of get and Tuple.



    Otherwise you can put all in a personal namespace (so myNs::get and myNs::Tuple.






    share|improve this answer

























      Your Answer






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

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

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

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


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f49328379%2fpartial-specialization-does-not-use-any-of-its-template-parameters%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









      1














      Your get's primary template is:



      template<int N, class... A>
      struct get{ ... };


      your get's partial specialization is:



      template<class R, class... A>
      struct get<0>{ ... };


      The specialization is receiving a single template argument, i.e.: 0, but the primary template above takes two template parameters:




      • the non-type template parameter N.

      • the variadic type parameter A.


      Besides, how can R be deduced?





      Specializing get instead as:



      template<class R, class... A>
      struct get<0, R, A...>{ ... };


      will make possible R to be deduced: it will be deduced to the type of the first element of the passed variadic argument. For example, in:



      get<0, int, float, double> foo;


      R will be deduced to int.






      share|improve this answer






























        1














        Your get's primary template is:



        template<int N, class... A>
        struct get{ ... };


        your get's partial specialization is:



        template<class R, class... A>
        struct get<0>{ ... };


        The specialization is receiving a single template argument, i.e.: 0, but the primary template above takes two template parameters:




        • the non-type template parameter N.

        • the variadic type parameter A.


        Besides, how can R be deduced?





        Specializing get instead as:



        template<class R, class... A>
        struct get<0, R, A...>{ ... };


        will make possible R to be deduced: it will be deduced to the type of the first element of the passed variadic argument. For example, in:



        get<0, int, float, double> foo;


        R will be deduced to int.






        share|improve this answer




























          1












          1








          1







          Your get's primary template is:



          template<int N, class... A>
          struct get{ ... };


          your get's partial specialization is:



          template<class R, class... A>
          struct get<0>{ ... };


          The specialization is receiving a single template argument, i.e.: 0, but the primary template above takes two template parameters:




          • the non-type template parameter N.

          • the variadic type parameter A.


          Besides, how can R be deduced?





          Specializing get instead as:



          template<class R, class... A>
          struct get<0, R, A...>{ ... };


          will make possible R to be deduced: it will be deduced to the type of the first element of the passed variadic argument. For example, in:



          get<0, int, float, double> foo;


          R will be deduced to int.






          share|improve this answer















          Your get's primary template is:



          template<int N, class... A>
          struct get{ ... };


          your get's partial specialization is:



          template<class R, class... A>
          struct get<0>{ ... };


          The specialization is receiving a single template argument, i.e.: 0, but the primary template above takes two template parameters:




          • the non-type template parameter N.

          • the variadic type parameter A.


          Besides, how can R be deduced?





          Specializing get instead as:



          template<class R, class... A>
          struct get<0, R, A...>{ ... };


          will make possible R to be deduced: it will be deduced to the type of the first element of the passed variadic argument. For example, in:



          get<0, int, float, double> foo;


          R will be deduced to int.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 16 '18 at 20:11

























          answered Mar 16 '18 at 19:57









          ネロクネロク

          10.5k32140




          10.5k32140

























              1














              Maybe you have to partial specialize get as follows



              template<class R, class... A>
              struct get<0, R, A...> {
              R operator()(Tuple<R, A...> t) {
              return t.first();
              }
              };


              I mean... get<0, R, A...>, not get<0>



              But you have also to modify the main get to call the following call with the correct type list, so



              template<int N, typename A0, typename ... As>
              struct get {
              auto operator()(Tuple<A0, As...> t) {
              return get<N-1, As...>()(t.base());
              }
              };


              Otherwise you can also demand the types management to a template version of the operator() and maintain only the int N value for get



              template <int N>
              struct get
              {
              template <typename Tpl>
              auto operator() (Tpl t)
              -> decltype( get<N-1>()(t.base()) )
              { return get<N-1>()(t.base()); }
              };

              template<>
              struct get<0>
              {
              template <typename Tpl>
              auto operator() (Tpl t)
              -> decltype ( t.first() )
              { return t.first(); }
              };


              Starting from C++14 you can avoid the decltype() part.



              Off topic suggestion: avoid the use of names that can collide with std namespace names.



              Maybe myGet and myTuple instead of get and Tuple.



              Otherwise you can put all in a personal namespace (so myNs::get and myNs::Tuple.






              share|improve this answer






























                1














                Maybe you have to partial specialize get as follows



                template<class R, class... A>
                struct get<0, R, A...> {
                R operator()(Tuple<R, A...> t) {
                return t.first();
                }
                };


                I mean... get<0, R, A...>, not get<0>



                But you have also to modify the main get to call the following call with the correct type list, so



                template<int N, typename A0, typename ... As>
                struct get {
                auto operator()(Tuple<A0, As...> t) {
                return get<N-1, As...>()(t.base());
                }
                };


                Otherwise you can also demand the types management to a template version of the operator() and maintain only the int N value for get



                template <int N>
                struct get
                {
                template <typename Tpl>
                auto operator() (Tpl t)
                -> decltype( get<N-1>()(t.base()) )
                { return get<N-1>()(t.base()); }
                };

                template<>
                struct get<0>
                {
                template <typename Tpl>
                auto operator() (Tpl t)
                -> decltype ( t.first() )
                { return t.first(); }
                };


                Starting from C++14 you can avoid the decltype() part.



                Off topic suggestion: avoid the use of names that can collide with std namespace names.



                Maybe myGet and myTuple instead of get and Tuple.



                Otherwise you can put all in a personal namespace (so myNs::get and myNs::Tuple.






                share|improve this answer




























                  1












                  1








                  1







                  Maybe you have to partial specialize get as follows



                  template<class R, class... A>
                  struct get<0, R, A...> {
                  R operator()(Tuple<R, A...> t) {
                  return t.first();
                  }
                  };


                  I mean... get<0, R, A...>, not get<0>



                  But you have also to modify the main get to call the following call with the correct type list, so



                  template<int N, typename A0, typename ... As>
                  struct get {
                  auto operator()(Tuple<A0, As...> t) {
                  return get<N-1, As...>()(t.base());
                  }
                  };


                  Otherwise you can also demand the types management to a template version of the operator() and maintain only the int N value for get



                  template <int N>
                  struct get
                  {
                  template <typename Tpl>
                  auto operator() (Tpl t)
                  -> decltype( get<N-1>()(t.base()) )
                  { return get<N-1>()(t.base()); }
                  };

                  template<>
                  struct get<0>
                  {
                  template <typename Tpl>
                  auto operator() (Tpl t)
                  -> decltype ( t.first() )
                  { return t.first(); }
                  };


                  Starting from C++14 you can avoid the decltype() part.



                  Off topic suggestion: avoid the use of names that can collide with std namespace names.



                  Maybe myGet and myTuple instead of get and Tuple.



                  Otherwise you can put all in a personal namespace (so myNs::get and myNs::Tuple.






                  share|improve this answer















                  Maybe you have to partial specialize get as follows



                  template<class R, class... A>
                  struct get<0, R, A...> {
                  R operator()(Tuple<R, A...> t) {
                  return t.first();
                  }
                  };


                  I mean... get<0, R, A...>, not get<0>



                  But you have also to modify the main get to call the following call with the correct type list, so



                  template<int N, typename A0, typename ... As>
                  struct get {
                  auto operator()(Tuple<A0, As...> t) {
                  return get<N-1, As...>()(t.base());
                  }
                  };


                  Otherwise you can also demand the types management to a template version of the operator() and maintain only the int N value for get



                  template <int N>
                  struct get
                  {
                  template <typename Tpl>
                  auto operator() (Tpl t)
                  -> decltype( get<N-1>()(t.base()) )
                  { return get<N-1>()(t.base()); }
                  };

                  template<>
                  struct get<0>
                  {
                  template <typename Tpl>
                  auto operator() (Tpl t)
                  -> decltype ( t.first() )
                  { return t.first(); }
                  };


                  Starting from C++14 you can avoid the decltype() part.



                  Off topic suggestion: avoid the use of names that can collide with std namespace names.



                  Maybe myGet and myTuple instead of get and Tuple.



                  Otherwise you can put all in a personal namespace (so myNs::get and myNs::Tuple.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Mar 16 '18 at 20:15

























                  answered Mar 16 '18 at 19:54









                  max66max66

                  35.1k73763




                  35.1k73763






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


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

                      But avoid



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

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


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




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f49328379%2fpartial-specialization-does-not-use-any-of-its-template-parameters%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

                      Ottavio Pratesi

                      Tricia Helfer

                      15 giugno