Template instantiation for nested class












-1












$begingroup$


In trying to code an iterator, I have the following structure:



template <typename T> class mything {
typedef unsigned key;
public:
template <typename subT> class myiter {
key pos;
public:
...
}
using iterator = myiter<T>;
using const_iterator = myiter<const T>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;

iterator begin() { return { 0 }; }
...
};


and would like to add the traits by declaring std::iterator_traits<...>. I tried



template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> { ... }


however, this results in a compiler error: "template parameters not deducible in partial specialization:" I tried just



template<typename T> struct std::iterator_traits<typename mything<T>::template myiter<T>> { ... }


which at least is accepted by the compiler, but the trait is not defined, so later in std::reverse_iterator I get the error: "no type named 'iterator_category' in 'struct std::iterator_traits::myiter >'
class reverse_iterator".



The only thing that compiles, for now, is to explicity declare



template<> struct std::iterator_traits<mything<int>::myiter<int>> { ... }


which obviously I don't want to do for all the classes.



Here is a minimal working example: changing #if 0 to #if 1 produces the errors.



#include <iterator>

template <typename T> T myobj = 0;

template <typename T> class mything {
typedef unsigned key;
public:
template <typename subT> class myiter {
key pos;
public:
myiter(key _pos) : pos(_pos) { }
subT &operator *() const { return myobj<subT>; }
myiter operator ++() { return myiter(pos+1); }
myiter operator --() { return myiter(pos-1); }
std::ptrdiff_t operator-(const myiter &that) const { return pos-that.pos; }
};

using iterator = myiter<T>;
using const_iterator = myiter<const T>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;

iterator begin() { return { 0 }; }
iterator end() { return { 10 }; }
const_iterator begin() const { return { 0 }; }
const_iterator end() const { return { 10 }; }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }

reverse_iterator rbegin() { return reverse_iterator{end()}; }
reverse_iterator rend() { return reverse_iterator{begin()}; }
const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; }
const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; }
const_reverse_iterator crbegin() const { return rbegin(); }
const_reverse_iterator crend() const { return rend(); }
};

#if 0
template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> {
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
using value_type = subT;
using pointer = subT*;
using reference = subT&;
using iterator_category = std::random_access_iterator_tag;
};

#else
template <> struct std::iterator_traits<mything<int>::myiter<int>> {
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
using value_type = int;
using pointer = int*;
using reference = int&;
using iterator_category = std::random_access_iterator_tag;
};

template <> struct std::iterator_traits<mything<int>::myiter<const int>> {
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
using value_type = const int;
using pointer = const int*;
using reference = const int&;
using iterator_category = std::random_access_iterator_tag;
};
#endif

#include <cassert>
#include <iostream>
#include <sstream>
int main(void) {
mything<int> thing;

std::ostringstream s;
std::copy(thing.cbegin(), thing.cend(), std::ostream_iterator<const int>(s, " "));
assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

s.str("");
std::copy(thing.rbegin(), thing.rend(), std::ostream_iterator<const int>(s, " "));
assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

auto const& ro_thing = thing;
s.str("");
std::copy(ro_thing.cbegin(), ro_thing.cend(), std::ostream_iterator<const int>(s, " "));
assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");
s.str("");
std::copy(ro_thing.rbegin(), ro_thing.rend(), std::ostream_iterator<const int>(s, " "));
assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

return 0;
}








share







New contributor




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







$endgroup$

















    -1












    $begingroup$


    In trying to code an iterator, I have the following structure:



    template <typename T> class mything {
    typedef unsigned key;
    public:
    template <typename subT> class myiter {
    key pos;
    public:
    ...
    }
    using iterator = myiter<T>;
    using const_iterator = myiter<const T>;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    iterator begin() { return { 0 }; }
    ...
    };


    and would like to add the traits by declaring std::iterator_traits<...>. I tried



    template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> { ... }


    however, this results in a compiler error: "template parameters not deducible in partial specialization:" I tried just



    template<typename T> struct std::iterator_traits<typename mything<T>::template myiter<T>> { ... }


    which at least is accepted by the compiler, but the trait is not defined, so later in std::reverse_iterator I get the error: "no type named 'iterator_category' in 'struct std::iterator_traits::myiter >'
    class reverse_iterator".



    The only thing that compiles, for now, is to explicity declare



    template<> struct std::iterator_traits<mything<int>::myiter<int>> { ... }


    which obviously I don't want to do for all the classes.



    Here is a minimal working example: changing #if 0 to #if 1 produces the errors.



    #include <iterator>

    template <typename T> T myobj = 0;

    template <typename T> class mything {
    typedef unsigned key;
    public:
    template <typename subT> class myiter {
    key pos;
    public:
    myiter(key _pos) : pos(_pos) { }
    subT &operator *() const { return myobj<subT>; }
    myiter operator ++() { return myiter(pos+1); }
    myiter operator --() { return myiter(pos-1); }
    std::ptrdiff_t operator-(const myiter &that) const { return pos-that.pos; }
    };

    using iterator = myiter<T>;
    using const_iterator = myiter<const T>;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    iterator begin() { return { 0 }; }
    iterator end() { return { 10 }; }
    const_iterator begin() const { return { 0 }; }
    const_iterator end() const { return { 10 }; }
    const_iterator cbegin() const { return begin(); }
    const_iterator cend() const { return end(); }

    reverse_iterator rbegin() { return reverse_iterator{end()}; }
    reverse_iterator rend() { return reverse_iterator{begin()}; }
    const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; }
    const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; }
    const_reverse_iterator crbegin() const { return rbegin(); }
    const_reverse_iterator crend() const { return rend(); }
    };

    #if 0
    template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> {
    using difference_type = std::ptrdiff_t;
    using size_type = std::size_t;
    using value_type = subT;
    using pointer = subT*;
    using reference = subT&;
    using iterator_category = std::random_access_iterator_tag;
    };

    #else
    template <> struct std::iterator_traits<mything<int>::myiter<int>> {
    using difference_type = std::ptrdiff_t;
    using size_type = std::size_t;
    using value_type = int;
    using pointer = int*;
    using reference = int&;
    using iterator_category = std::random_access_iterator_tag;
    };

    template <> struct std::iterator_traits<mything<int>::myiter<const int>> {
    using difference_type = std::ptrdiff_t;
    using size_type = std::size_t;
    using value_type = const int;
    using pointer = const int*;
    using reference = const int&;
    using iterator_category = std::random_access_iterator_tag;
    };
    #endif

    #include <cassert>
    #include <iostream>
    #include <sstream>
    int main(void) {
    mything<int> thing;

    std::ostringstream s;
    std::copy(thing.cbegin(), thing.cend(), std::ostream_iterator<const int>(s, " "));
    assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

    s.str("");
    std::copy(thing.rbegin(), thing.rend(), std::ostream_iterator<const int>(s, " "));
    assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

    auto const& ro_thing = thing;
    s.str("");
    std::copy(ro_thing.cbegin(), ro_thing.cend(), std::ostream_iterator<const int>(s, " "));
    assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");
    s.str("");
    std::copy(ro_thing.rbegin(), ro_thing.rend(), std::ostream_iterator<const int>(s, " "));
    assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

    return 0;
    }








    share







    New contributor




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







    $endgroup$















      -1












      -1








      -1





      $begingroup$


      In trying to code an iterator, I have the following structure:



      template <typename T> class mything {
      typedef unsigned key;
      public:
      template <typename subT> class myiter {
      key pos;
      public:
      ...
      }
      using iterator = myiter<T>;
      using const_iterator = myiter<const T>;
      using reverse_iterator = std::reverse_iterator<iterator>;
      using const_reverse_iterator = std::reverse_iterator<const_iterator>;

      iterator begin() { return { 0 }; }
      ...
      };


      and would like to add the traits by declaring std::iterator_traits<...>. I tried



      template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> { ... }


      however, this results in a compiler error: "template parameters not deducible in partial specialization:" I tried just



      template<typename T> struct std::iterator_traits<typename mything<T>::template myiter<T>> { ... }


      which at least is accepted by the compiler, but the trait is not defined, so later in std::reverse_iterator I get the error: "no type named 'iterator_category' in 'struct std::iterator_traits::myiter >'
      class reverse_iterator".



      The only thing that compiles, for now, is to explicity declare



      template<> struct std::iterator_traits<mything<int>::myiter<int>> { ... }


      which obviously I don't want to do for all the classes.



      Here is a minimal working example: changing #if 0 to #if 1 produces the errors.



      #include <iterator>

      template <typename T> T myobj = 0;

      template <typename T> class mything {
      typedef unsigned key;
      public:
      template <typename subT> class myiter {
      key pos;
      public:
      myiter(key _pos) : pos(_pos) { }
      subT &operator *() const { return myobj<subT>; }
      myiter operator ++() { return myiter(pos+1); }
      myiter operator --() { return myiter(pos-1); }
      std::ptrdiff_t operator-(const myiter &that) const { return pos-that.pos; }
      };

      using iterator = myiter<T>;
      using const_iterator = myiter<const T>;
      using reverse_iterator = std::reverse_iterator<iterator>;
      using const_reverse_iterator = std::reverse_iterator<const_iterator>;

      iterator begin() { return { 0 }; }
      iterator end() { return { 10 }; }
      const_iterator begin() const { return { 0 }; }
      const_iterator end() const { return { 10 }; }
      const_iterator cbegin() const { return begin(); }
      const_iterator cend() const { return end(); }

      reverse_iterator rbegin() { return reverse_iterator{end()}; }
      reverse_iterator rend() { return reverse_iterator{begin()}; }
      const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; }
      const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; }
      const_reverse_iterator crbegin() const { return rbegin(); }
      const_reverse_iterator crend() const { return rend(); }
      };

      #if 0
      template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> {
      using difference_type = std::ptrdiff_t;
      using size_type = std::size_t;
      using value_type = subT;
      using pointer = subT*;
      using reference = subT&;
      using iterator_category = std::random_access_iterator_tag;
      };

      #else
      template <> struct std::iterator_traits<mything<int>::myiter<int>> {
      using difference_type = std::ptrdiff_t;
      using size_type = std::size_t;
      using value_type = int;
      using pointer = int*;
      using reference = int&;
      using iterator_category = std::random_access_iterator_tag;
      };

      template <> struct std::iterator_traits<mything<int>::myiter<const int>> {
      using difference_type = std::ptrdiff_t;
      using size_type = std::size_t;
      using value_type = const int;
      using pointer = const int*;
      using reference = const int&;
      using iterator_category = std::random_access_iterator_tag;
      };
      #endif

      #include <cassert>
      #include <iostream>
      #include <sstream>
      int main(void) {
      mything<int> thing;

      std::ostringstream s;
      std::copy(thing.cbegin(), thing.cend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

      s.str("");
      std::copy(thing.rbegin(), thing.rend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

      auto const& ro_thing = thing;
      s.str("");
      std::copy(ro_thing.cbegin(), ro_thing.cend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");
      s.str("");
      std::copy(ro_thing.rbegin(), ro_thing.rend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

      return 0;
      }








      share







      New contributor




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







      $endgroup$




      In trying to code an iterator, I have the following structure:



      template <typename T> class mything {
      typedef unsigned key;
      public:
      template <typename subT> class myiter {
      key pos;
      public:
      ...
      }
      using iterator = myiter<T>;
      using const_iterator = myiter<const T>;
      using reverse_iterator = std::reverse_iterator<iterator>;
      using const_reverse_iterator = std::reverse_iterator<const_iterator>;

      iterator begin() { return { 0 }; }
      ...
      };


      and would like to add the traits by declaring std::iterator_traits<...>. I tried



      template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> { ... }


      however, this results in a compiler error: "template parameters not deducible in partial specialization:" I tried just



      template<typename T> struct std::iterator_traits<typename mything<T>::template myiter<T>> { ... }


      which at least is accepted by the compiler, but the trait is not defined, so later in std::reverse_iterator I get the error: "no type named 'iterator_category' in 'struct std::iterator_traits::myiter >'
      class reverse_iterator".



      The only thing that compiles, for now, is to explicity declare



      template<> struct std::iterator_traits<mything<int>::myiter<int>> { ... }


      which obviously I don't want to do for all the classes.



      Here is a minimal working example: changing #if 0 to #if 1 produces the errors.



      #include <iterator>

      template <typename T> T myobj = 0;

      template <typename T> class mything {
      typedef unsigned key;
      public:
      template <typename subT> class myiter {
      key pos;
      public:
      myiter(key _pos) : pos(_pos) { }
      subT &operator *() const { return myobj<subT>; }
      myiter operator ++() { return myiter(pos+1); }
      myiter operator --() { return myiter(pos-1); }
      std::ptrdiff_t operator-(const myiter &that) const { return pos-that.pos; }
      };

      using iterator = myiter<T>;
      using const_iterator = myiter<const T>;
      using reverse_iterator = std::reverse_iterator<iterator>;
      using const_reverse_iterator = std::reverse_iterator<const_iterator>;

      iterator begin() { return { 0 }; }
      iterator end() { return { 10 }; }
      const_iterator begin() const { return { 0 }; }
      const_iterator end() const { return { 10 }; }
      const_iterator cbegin() const { return begin(); }
      const_iterator cend() const { return end(); }

      reverse_iterator rbegin() { return reverse_iterator{end()}; }
      reverse_iterator rend() { return reverse_iterator{begin()}; }
      const_reverse_iterator rbegin() const { return const_reverse_iterator{end()}; }
      const_reverse_iterator rend() const { return const_reverse_iterator{begin()}; }
      const_reverse_iterator crbegin() const { return rbegin(); }
      const_reverse_iterator crend() const { return rend(); }
      };

      #if 0
      template<typename T,typename subT> struct std::iterator_traits<typename mything<T>::template myiter<subT>> {
      using difference_type = std::ptrdiff_t;
      using size_type = std::size_t;
      using value_type = subT;
      using pointer = subT*;
      using reference = subT&;
      using iterator_category = std::random_access_iterator_tag;
      };

      #else
      template <> struct std::iterator_traits<mything<int>::myiter<int>> {
      using difference_type = std::ptrdiff_t;
      using size_type = std::size_t;
      using value_type = int;
      using pointer = int*;
      using reference = int&;
      using iterator_category = std::random_access_iterator_tag;
      };

      template <> struct std::iterator_traits<mything<int>::myiter<const int>> {
      using difference_type = std::ptrdiff_t;
      using size_type = std::size_t;
      using value_type = const int;
      using pointer = const int*;
      using reference = const int&;
      using iterator_category = std::random_access_iterator_tag;
      };
      #endif

      #include <cassert>
      #include <iostream>
      #include <sstream>
      int main(void) {
      mything<int> thing;

      std::ostringstream s;
      std::copy(thing.cbegin(), thing.cend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

      s.str("");
      std::copy(thing.rbegin(), thing.rend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

      auto const& ro_thing = thing;
      s.str("");
      std::copy(ro_thing.cbegin(), ro_thing.cend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");
      s.str("");
      std::copy(ro_thing.rbegin(), ro_thing.rend(), std::ostream_iterator<const int>(s, " "));
      assert(s.str() == "0 0 0 0 0 0 0 0 0 0 ");

      return 0;
      }






      c++ c++11 template





      share







      New contributor




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










      share







      New contributor




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








      share



      share






      New contributor




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









      asked 3 mins ago









      grokgrok

      971




      971




      New contributor




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





      New contributor





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






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






















          0






          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          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: "196"
          };
          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: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          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
          });


          }
          });






          grok 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%2fcodereview.stackexchange.com%2fquestions%2f214224%2ftemplate-instantiation-for-nested-class%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








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










          draft saved

          draft discarded


















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













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












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
















          Thanks for contributing an answer to Code Review Stack Exchange!


          • 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.


          Use MathJax to format equations. MathJax reference.


          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%2fcodereview.stackexchange.com%2fquestions%2f214224%2ftemplate-instantiation-for-nested-class%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

          404 Error Contact Form 7 ajax form submitting

          How to know if a Active Directory user can login interactively

          Refactoring coordinates for Minecraft Pi buildings written in Python