I am trying to implement concept checking for a couple of MPL concepts as
part of a large project. I've having a heck of a time with some aspects of
this.
The example below illustrates one of the problems I'm having.
The intent is to test the concept. for next<I>, the concept
check is invoked recurrsively until the end of iteration is
encountered. (I'm assuming it's a list in this test). But the
is_end
On Mon, 12 Dec 2011, Robert Ramey wrote:
I am trying to implement concept checking for a couple of MPL concepts as part of a large project. I've having a heck of a time with some aspects of this.
The example below illustrates one of the problems I'm having. The intent is to test the concept. for next<I>, the concept check is invoked recurrsively until the end of iteration is encountered. (I'm assuming it's a list in this test). But the is_end
branch is always invoked leading to failure on both MSVC 9.0 and gcc 4.5.3 compilers I'll be quite impressed with anyone who can figure out how to make this work.
May I please get a version of this with the headers and "using namespace" declarations that are needed? I'm having trouble getting the basic parts of this to compile on GCC 4.6. -- Jeremiah Willcock
On 12/12/11 13:41, Robert Ramey wrote: [snip]
The example below illustrates one of the problems I'm having. The intent is to test the concept. for next<I>, the concept check is invoked recurrsively until the end of iteration is encountered. (I'm assuming it's a list in this test). But the is_end
branch is always invoked [snip] template<typename S> struct ForwardSequence { typedef typename end<S>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> ));
Shouldn't this:
is_end
branch is always invoked
be expected since end<S>::type is being passed to ForwardIterator? [snip]
On 12/12/11 15:01, Larry Evans wrote:
On 12/12/11 13:41, Robert Ramey wrote: [snip]
The example below illustrates one of the problems I'm having. The intent is to test the concept. for next<I>, the concept check is invoked recurrsively until the end of iteration is encountered. (I'm assuming it's a list in this test). But the is_end
branch is always invoked [snip] template<typename S> struct ForwardSequence { typedef typename end<S>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> )); Shouldn't this:
is_end
branch is always invoked be expected since end<S>::type is being passed to ForwardIterator? [snip] OOPS, never mind. I see you intentionally passed the end<S>::type to show the very problem you mentioned. IOW, even though end<S>::type is passed, the false_ branch is taken instead of the true_ brancch.
Sorry for noise. However I haved tried to compile the attached: and, with gcc4.7, I'm getting: ramey_iter_concept_check.cpp:19:14: error: explicit specialization in non-namespace scope 'struct boost::mpl::ForwardIterator<I>' ramey_iter_concept_check.cpp:20:12: error: template parameters not used in partial specialization:
On 12/12/11 13:41, Robert Ramey wrote:
I am trying to implement concept checking for a couple of MPL concepts as part of a large project. I've having a heck of a time with some aspects of this.
The example below illustrates one of the problems I'm having. The intent is to test the concept. for next<I>, the concept
Does ForwardIterator<I> attempt to test that all elements in
the iterator, I, satisfy some concept? If so, then I don't
see any test for that within the is_end
check is invoked recurrsively until the end of iteration is encountered. (I'm assuming it's a list in this test). But the is_end
branch is always invoked leading to failure on both MSVC 9.0 and gcc 4.5.3 compilers
I couldn't get this code to compile with gcc4.7, even after making the modifications shown in the attached. Instead, I get the error message: ramey_iter_concept_check.cpp:34:10: error: invalid explicit specialization before '>' token ramey_iter_concept_check.cpp:34:10: error: enclosing class templates are not explicitly specialized ramey_iter_concept_check.cpp:35:28: error: template parameters not used in partial specialization: ramey_iter_concept_check.cpp:35:28: error: 'I' The reason the specialization was moved outside of the containing class was because gcc said you couldn't specialize a nested template in the class declaration; however, even when the is_end specialization was moved outside the class declaration, the above error message occurred. I'm surprised gcc 4.5.3 compiles your code because, IIRC, the problem of nested template specializations has been around for some time.
I'll be quite impressed with anyone who can figure out how to make this work.
Robert Ramey
template<typename I> struct ForwardIterator { template<typename B> struct is_end {}; template<> struct is_end
{ typedef typename deref<I>::type t1; typedef typename next<I>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> )); }; typedef typename boost::mpl::print< I >::type t1; typedef typename is_end< typename boost::is_same< boost::mpl::l_iterboost::mpl::l_end, I > > type; BOOST_MPL_ASSERT(( is_convertible< typename I::category, forward_iterator_tag > )); }; template<typename S> struct ForwardSequence { typedef typename end<S>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> )); };
#include
void test_list_sequence(){ BOOST_CONCEPT_ASSERT(( boost::mpl::ForwardSequence< boost::mpl::list > )); }
On 12/12/11 16:30, Larry Evans wrote:
On 12/12/11 13:41, Robert Ramey wrote:
I am trying to implement concept checking for a couple of MPL concepts as part of a large project. I've having a heck of a time with some aspects of this. [snip] Maybe the if_recur template shown here:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/libs/mpl/sandbox/i...
would be some help.
Or even the while_ template here: http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/mpl/while.hp... AFAICT, a similar problem was discussed here: http://article.gmane.org/gmane.comp.lib.boost.devel/190874 HTH. -regards, Larry
On Mon, 12 Dec 2011, Robert Ramey wrote:
I am trying to implement concept checking for a couple of MPL concepts as part of a large project. I've having a heck of a time with some aspects of this.
The example below illustrates one of the problems I'm having. The intent is to test the concept. for next<I>, the concept check is invoked recurrsively until the end of iteration is encountered. (I'm assuming it's a list in this test). But the is_end
branch is always invoked leading to failure on both MSVC 9.0 and gcc 4.5.3 compilers I'll be quite impressed with anyone who can figure out how to make this work.
Here's my version:
template<typename I>
struct ForwardIterator;
template
On 12/12/11 16:39, Jeremiah Willcock wrote: [snip]
Here's my version:
template<typename I> struct ForwardIterator;
template
struct check_unless_end {}; template <typename I> struct check_unless_end { typedef typename boost::mpl::deref<I>::type t1; typedef typename boost::mpl::next<I>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> )); };
template<typename I> struct ForwardIterator { typedef typename boost::mpl::print< I >::type t1; typedef check_unless_end< I, boost::is_same< boost::mpl::l_iterboost::mpl::l_end, I > > t2; BOOST_MPL_ASSERT(( boost::is_convertible< typename I::category, boost::mpl::forward_iterator_tag > )); };
template<typename S> struct ForwardSequence { typedef typename boost::mpl::end<S>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> )); };
#include
void test_list_sequence(){ BOOST_CONCEPT_ASSERT(( ForwardSequence< boost::mpl::list > )); } -- Jeremiah Willcock Hi Jeremiah,
After adding the #include's shown in the attached, I got warning: k/boost/mpl/print.hpp:55:10: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] Simply rm'ing the print typedef solved the problem and seems harmless since the t1 is not used anywhere. Looking at your code, it seems you solved the problem by removing the nested specialization of is_end, with a specialization in file scope of check_unless_end. I've a vague memory of hearing some similar solution elsewhere. Is there some reason why specializations cannot occur within the class? -regards, Larry
On 12/12/11 17:04, Larry Evans wrote:
On 12/12/11 16:39, Jeremiah Willcock wrote: [snip] Looking at your code, it seems you solved the problem by removing the nested specialization of is_end, with a specialization in file scope of check_unless_end. I've a vague memory of hearing some similar solution elsewhere. Is there some reason why specializations cannot occur within the class?
-regards, Larry
The reason is explained in this thread: http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/c04... and the workaround which Jeremiah showed is also found here: http://stackoverflow.com/questions/2537716/why-is-partial-specialziation-of-... after the phrase: You can work around this behavior by delegating the real work to another structure though: HTH. -regards, Larry
On Mon, 12 Dec 2011, Larry Evans wrote:
On 12/12/11 17:04, Larry Evans wrote:
On 12/12/11 16:39, Jeremiah Willcock wrote: [snip] Looking at your code, it seems you solved the problem by removing the nested specialization of is_end, with a specialization in file scope of check_unless_end. I've a vague memory of hearing some similar solution elsewhere. Is there some reason why specializations cannot occur within the class?
-regards, Larry
The reason is explained in this thread:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/c04...
I don't see anything in that thread that talks about why member templates can't be specialized in-class. I don't see a good reason for that limitation; how is a class member specialization different from one in a namespace other than that there can be template parameters on the class itself? -- Jeremiah Willcock
On 12/12/11 19:31, Jeremiah Willcock wrote:
On Mon, 12 Dec 2011, Larry Evans wrote:
On 12/12/11 17:04, Larry Evans wrote:
On 12/12/11 16:39, Jeremiah Willcock wrote: [snip] Looking at your code, it seems you solved the problem by removing the nested specialization of is_end, with a specialization in file scope of check_unless_end. I've a vague memory of hearing some similar solution elsewhere. Is there some reason why specializations cannot occur within the class?
-regards, Larry
The reason is explained in this thread:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/c04...
I don't see anything in that thread that talks about why member templates can't be specialized in-class. I don't see a good reason for that limitation; how is a class member specialization different from one in a namespace other than that there can be template parameters on the class itself?
-- Jeremiah Willcock OOPS, you're right. The situation was just so similar ( specialization of nested template class within an outer template class) that I thought the reason given would apply, but I guess not.
Thanks for pointing out my error. -regards, Larry
Jeremiah Willcock wrote:
On Mon, 12 Dec 2011, Larry Evans wrote:
On 12/12/11 17:04, Larry Evans wrote:
On 12/12/11 16:39, Jeremiah Willcock wrote: [snip] Looking at your code, it seems you solved the problem by removing the nested specialization of is_end, with a specialization in file scope of check_unless_end. I've a vague memory of hearing some similar solution elsewhere. Is there some reason why specializations cannot occur within the class?
-regards, Larry
The reason is explained in this thread:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/c04...
I don't see anything in that thread that talks about why member templates can't be specialized in-class. I don't see a good reason for that limitation; how is a class member specialization different from one in a namespace other than that there can be template parameters on the class itself?
-- Jeremiah Willcock
First of all I want to thank everyone who contributed to this thread. I
carefully read
every single message and the links. I was really lost.
I was really bothered with the idea that the template specialization would
work
outside the class but not in it - as you were. The links didn't seem on
point on
this subject. I took my original solution and moved the specializations
outside
the class. This failed because the I wasn't defined so I added it do the
template
arguments. Then a few syntax corrections and it started to work - OK,
problem solved - but now I was left with this really annoying feature whose
behavior changed when the specialization was moved out side the class. So
I moved it back in - and voila - worked as expected. Here is my solution:
template<typename I>
struct ForwardIterator {
template
On 12/12/11 22:49, Robert Ramey wrote:
Jeremiah Willcock wrote:
On Mon, 12 Dec 2011, Larry Evans wrote:
On 12/12/11 17:04, Larry Evans wrote:
On 12/12/11 16:39, Jeremiah Willcock wrote: [snip] Looking at your code, it seems you solved the problem by removing the nested specialization of is_end, with a specialization in file scope of check_unless_end. I've a vague memory of hearing some similar solution elsewhere. Is there some reason why specializations cannot occur within the class?
-regards, Larry
The reason is explained in this thread:
http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/c04...
I don't see anything in that thread that talks about why member templates can't be specialized in-class. I don't see a good reason for that limitation; how is a class member specialization different from one in a namespace other than that there can be template parameters on the class itself?
-- Jeremiah Willcock
First of all I want to thank everyone who contributed to this thread. I carefully read every single message and the links. I was really lost.
I was really bothered with the idea that the template specialization would work outside the class but not in it - as you were. The links didn't seem on point on this subject. I took my original solution and moved the specializations outside the class. This failed because the I wasn't defined so I added it do the template arguments. Then a few syntax corrections and it started to work - OK, problem solved - but now I was left with this really annoying feature whose behavior changed when the specialization was moved out side the class. So I moved it back in - and voila - worked as expected. Here is my solution:
template<typename I> struct ForwardIterator { template
struct is_end {}; template<typename I2> struct is_end
{ typedef typename deref<I2>::type t1; typedef typename next<I2>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> )); }; typedef typename is_end< I, typename boost::is_same< boost::mpl::l_iterboost::mpl::l_end, I > > type; typedef typename boost::mpl::print< I >::type t1;
BOOST_MPL_ASSERT(( is_convertible< typename I::category, forward_iterator_tag > )); };
Basically, I just had to avoid depending on the "outter" template parameter. This had bothered me before but I wasn't aware of the right syntax to avoid it. I had to use the specialization syntax above rather than the template<> syntax I was familiar with. So I guess that resolves the problem.
Again, thanks for everyone who contributed - really would never have found it by myself.
Robert Ramey Hi Robert,
I couldn't get this code to compile with gcc-4.7-20111008. Before any revision, got: ramey_iter_concept_check.cpp:22:14: error: declaration of 'class I' ramey_iter_concept_check.cpp:20:10: error: shadows template parm 'class I' ramey_iter_concept_check.cpp:32:22: error: expected nested-name-specifier ramey_iter_concept_check.cpp:38:7: error: invalid declarator before 'type' After eliminating the showing I, as shown in the attached, I got: /home/evansl/download/gcc/4.7-20111008/install/bin/g++ -c -Wall -Wstrict-overflow -ftemplate-depth-300 -O0 -g3 -fno-inline -std=gnu++0x -I/home/evansl/prog_dev/boost-svn/ro/trunk/sandbox/ro/numeric_bindings -I/home/evansl/prog_dev/boost-svn/ro/trunk/sandbox/rw/non_variadic_templates -I/home/evansl/prog_dev/boost-svn/ro/trunk -DTEMPLATE_DEPTH=300 ramey_iter_concept_check.cpp -MMD -o build/gcc4_7n/boost-svn/ro/trunk/sandbox/rw/variadic_templates/libs/mpl/example/ramey_iter_concept_check.o ramey_iter_concept_check.cpp:31:22: error: expected nested-name-specifier ramey_iter_concept_check.cpp:37:7: error: invalid declarator before 'type' make: *** [build/gcc4_7n/boost-svn/ro/trunk/sandbox/rw/variadic_templates/libs/mpl/example/ramey_iter_concept_check.o] Error 1 I guess you're using MS or an earlier gcc. -regards, Larry
On 12/12/11 23:30, Larry Evans wrote:
On 12/12/11 22:49, Robert Ramey wrote: [snip]
I moved it back in - and voila - worked as expected. Here is my solution:
template<typename I> struct ForwardIterator { template
struct is_end {}; template<typename I2> struct is_end
{ typedef typename deref<I2>::type t1; typedef typename next<I2>::type t2; BOOST_CONCEPT_ASSERT(( ForwardIterator<t2> )); }; typedef typename is_end< I, typename boost::is_same< boost::mpl::l_iterboost::mpl::l_end, I > > type; typedef typename boost::mpl::print< I >::type t1;
BOOST_MPL_ASSERT(( is_convertible< typename I::category, forward_iterator_tag > )); };
[snip] I couldn't get this code to compile with gcc-4.7-20111008. Before any revision, got:
ramey_iter_concept_check.cpp:22:14: error: declaration of 'class I' ramey_iter_concept_check.cpp:20:10: error: shadows template parm 'class I' ramey_iter_concept_check.cpp:32:22: error: expected nested-name-specifier ramey_iter_concept_check.cpp:38:7: error: invalid declarator before 'type'
After eliminating the showing I, as shown in the attached, I got:
/home/evansl/download/gcc/4.7-20111008/install/bin/g++ -c -Wall -Wstrict-overflow -ftemplate-depth-300 -O0 -g3 -fno-inline -std=gnu++0x -I/home/evansl/prog_dev/boost-svn/ro/trunk/sandbox/ro/numeric_bindings -I/home/evansl/prog_dev/boost-svn/ro/trunk/sandbox/rw/non_variadic_templates -I/home/evansl/prog_dev/boost-svn/ro/trunk -DTEMPLATE_DEPTH=300 ramey_iter_concept_check.cpp -MMD -o build/gcc4_7n/boost-svn/ro/trunk/sandbox/rw/variadic_templates/libs/mpl/example/ramey_iter_concept_check.o
ramey_iter_concept_check.cpp:31:22: error: expected nested-name-specifier ramey_iter_concept_check.cpp:37:7: error: invalid declarator before 'type' make: *** [build/gcc4_7n/boost-svn/ro/trunk/sandbox/rw/variadic_templates/libs/mpl/example/ramey_iter_concept_check.o] Error 1
I guess you're using MS or an earlier gcc.
-regards, Larry Using the if_recur.hpp:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/mpl/if_recur... mentioned in one of my previous replies, the attached compiles; however, I'm not sure it does what you want. The in source comments reflect my questions. -regards, Larry
On 12/13/11 08:15, Larry Evans wrote: [snip]
Using the if_recur.hpp:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/mpl/if_recur...
mentioned in one of my previous replies, the attached compiles; however, I'm not sure it does what you want. The in source comments reflect my questions.
I think I figured why the t1 was not being used. That typedef was just there to check that the iterator could be deref'ed, AFAICT. I've not used the concept library before; hence, that may be why I'm having some trouble understanding what's required. The attached is a revised version of my previous code, but now only the ForwardSequence template is needed. The ForwardIterator template declarations has been moved to within the ForwardSequence. Also, in the attachment, t1 has been renamed to is_deref_able, since that seems more descriptive. Would this new ForwardSequence template satisfy your requirements? -regards, Larry
On 12/12/2011 8:49 PM, Robert Ramey wrote:
I was really bothered with the idea that the template specialization would work outside the class but not in it - as you were.
You're allowed to *partially* specialize a nested class template within the outer class. But full specialization of a nested class template must be done outside the outer class. I don't know the reason for this, and I don't have a reference, sorry. It's one of those bits of C++ arcana that I have squirreled away in my brain. Wish I could get those brain cells back. -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (4)
-
Eric Niebler
-
Jeremiah Willcock
-
Larry Evans
-
Robert Ramey