Template instantiation for nested class
$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;
}
c++ c++11 template
New contributor
$endgroup$
add a comment |
$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;
}
c++ c++11 template
New contributor
$endgroup$
add a comment |
$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;
}
c++ c++11 template
New contributor
$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
c++ c++11 template
New contributor
New contributor
New contributor
asked 3 mins ago
grokgrok
971
971
New contributor
New contributor
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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.
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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