[mpl] mpl::c_str fails for mpl::push_back

Hi, the following results in a compile error for msvc-10.0. It works for gcc-3.4, gcc-4.3, gcc-4.5. typedef mpl::vector_c<char, 'h','e','l','l','o',' ','w','o','r','l','d'> hello; typedef mpl::push_back<hello, mpl::char_<'!'> >::type hello2; BOOST_TEST((std::string(mpl::c_str<hello2>::value)== "hello world!")); // line 59 C:\cygwin\boost\v44\boost/mpl/string.hpp(592) : error C2039: 'value_type' : is not a member of 'boost::mpl::vector12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>' with [ T0=boost::mpl::integral_c<char,104>, T1=boost::mpl::integral_c<char,101>, T2=boost::mpl::integral_c<char,108>, T3=boost::mpl::integral_c<char,108>, T4=boost::mpl::integral_c<char,111>, T5=boost::mpl::integral_c<char,32>, T6=boost::mpl::integral_c<char,119>, T7=boost::mpl::integral_c<char,111>, T8=boost::mpl::integral_c<char,114>, T9=boost::mpl::integral_c<char,108>, T10=boost::mpl::integral_c<char,100>, T11=boost::mpl::char_<33> ] io\match_pass.cpp(59) : see reference to class template instantiation 'boost::mpl::c_str<Sequence>' being compiled with [ Sequence=hello2 ] Is this a known bug? Best, _____________________ Vicente Juan Botet Escribá http://viboes.blogspot.com/

On 11/6/2010 8:51 PM, vicente.botet wrote:
Hi,
the following results in a compile error for msvc-10.0. It works for gcc-3.4, gcc-4.3, gcc-4.5.
typedef mpl::vector_c<char, 'h','e','l','l','o',' ','w','o','r','l','d'> hello;
typedef mpl::push_back<hello, mpl::char_<'!'> >::type hello2;
BOOST_TEST((std::string(mpl::c_str<hello2>::value)== "hello world!")); // line 59
C:\cygwin\boost\v44\boost/mpl/string.hpp(592) : error C2039: 'value_type' : is not a member of 'boost::mpl::vector12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>' with [ T0=boost::mpl::integral_c<char,104>, T1=boost::mpl::integral_c<char,101>, T2=boost::mpl::integral_c<char,108>, T3=boost::mpl::integral_c<char,108>, T4=boost::mpl::integral_c<char,111>, T5=boost::mpl::integral_c<char,32>, T6=boost::mpl::integral_c<char,119>, T7=boost::mpl::integral_c<char,111>, T8=boost::mpl::integral_c<char,114>, T9=boost::mpl::integral_c<char,108>, T10=boost::mpl::integral_c<char,100>, T11=boost::mpl::char_<33> ] io\match_pass.cpp(59) : see reference to class template instantiation 'boost::mpl::c_str<Sequence>' being compiled with [ Sequence=hello2 ]
Is this a known bug?
mpl::c_str is for use with mpl::string. Does the problem also occur with mpl::string? -- Eric Niebler BoostPro Computing http://www.boostpro.com

----- Original Message ----- From: "Eric Niebler" <eric@boostpro.com> To: <boost@lists.boost.org> Sent: Sunday, November 07, 2010 2:15 AM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
On 11/6/2010 8:51 PM, vicente.botet wrote:
Hi,
the following results in a compile error for msvc-10.0. It works for gcc-3.4, gcc-4.3, gcc-4.5.
typedef mpl::vector_c<char, 'h','e','l','l','o',' ','w','o','r','l','d'> hello;
typedef mpl::push_back<hello, mpl::char_<'!'> >::type hello2;
BOOST_TEST((std::string(mpl::c_str<hello2>::value)== "hello world!")); // line 59
C:\cygwin\boost\v44\boost/mpl/string.hpp(592) : error C2039: 'value_type' : is not a member of 'boost::mpl::vector12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>' Is this a known bug?
mpl::c_str is for use with mpl::string. Does the problem also occur with mpl::string?
No push_back on a mpl::string is works as it is yet a Integral Sequence Wrapper. But push_back on a vector_c which is a Integral Sequence Wrapper is not a Integral Sequence Wrapper and this seems to me a more critical issue. BOOST_STATIC_ASSERT((boost::is_same<hello2::value_type,char>::value)); // compile fail I was loking for a way to represent static sequences of arbitrary chararcters types and mpl::string doesn't supports wchar_t, u16char or u32char so I though to move to vector_c. BTW, I have found the use of c_str in a MPL tests string.cpp typedef mpl::vector_c<char, 'a','b','c','d','e'> rgc; *** BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<rgc>::value)); typedef mpl::copy<rgc, mpl::back_inserter<mpl::string<> > >::type str; BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<str>::value)); I don't think I could find something in the doc that states that the push_back on a Integral Sequence Wrapper must be a Integral Sequence Wrapper, but I think that this is a desirable property. Do you have a workaround I can use to preserve it? Do you think that it is possible to ensure that property without too much trouble inside the library? Thanks, Vicente

----- Original Message ----- From: "vicente.botet" <vicente.botet@wanadoo.fr> To: <boost@lists.boost.org> Sent: Sunday, November 07, 2010 8:38 AM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
----- Original Message ----- From: "Eric Niebler" <eric@boostpro.com> To: <boost@lists.boost.org> Sent: Sunday, November 07, 2010 2:15 AM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
On 11/6/2010 8:51 PM, vicente.botet wrote:
Hi,
the following results in a compile error for msvc-10.0. It works for gcc-3.4, gcc-4.3, gcc-4.5.
typedef mpl::vector_c<char, 'h','e','l','l','o',' ','w','o','r','l','d'> hello;
typedef mpl::push_back<hello, mpl::char_<'!'> >::type hello2;
BOOST_TEST((std::string(mpl::c_str<hello2>::value)== "hello world!")); // line 59
mpl::c_str is for use with mpl::string. Does the problem also occur with mpl::string?
Ah, I've forget to ask: How is it that it works for gcc-3.4, gcc-4.3, gcc-4.5? Where is the value_type defined? Vicente

On Sun, 07 Nov 2010 02:00:42 -0600, vicente.botet <vicente.botet@wanadoo.fr> wrote:
Ah, I've forget to ask: How is it that it works for gcc-3.4, gcc-4.3, gcc-4.5? Where is the value_type defined?
It's an implementation artifact: GCC has typeof, and typeof-based vectors use inheritance to build push_back's result: template<> struct push_back_impl< aux::vector_tag > { template< typename Vector, typename T > struct apply { typedef v_item<T,Vector,0> type; }; }; template< typename T , typename Base , int at_front = 0 > struct v_item : Base { ... }; HTH, -- Aleksey Gurtovoy MetaCommunications Engineering

----- Original Message ----- From: "Aleksey Gurtovoy" <agurtovoy@meta-comm.com> To: <boost@lists.boost.org> Sent: Monday, November 08, 2010 10:55 AM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
On Sun, 07 Nov 2010 02:00:42 -0600, vicente.botet <vicente.botet@wanadoo.fr> wrote:
Ah, I've forget to ask: How is it that it works for gcc-3.4, gcc-4.3, gcc-4.5? Where is the value_type defined?
It's an implementation artifact: GCC has typeof, and typeof-based vectors use inheritance to build push_back's result:
<snip>
HTH,
yes. I wanted just to know if ths was normal. Best, Vicente

----- Original Message ----- From: "vicente.botet" <vicente.botet@wanadoo.fr> To: <boost@lists.boost.org> Sent: Sunday, November 07, 2010 8:38 AM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
Do you have a workaround I can use to preserve it?
I have tried to add a value_type trait template<typename Sequence> struct value_type { typedef typename Sequence::value_type type; }; changed the c_str to use the type trait template<typename Sequence> struct c_str { typedef typename mpl::end<Sequence>::type iend; typedef typename mpl::begin<Sequence>::type i0; #define M0(z, n, data) \ typedef \ typename mpl::aux_::next_unless<BOOST_PP_CAT(i, n), iend>::type \ BOOST_PP_CAT(i, BOOST_PP_INC(n)); BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~) #undef M0 typedef c_str type; static typename value_type<Sequence>::type const value[BOOST_MPL_LIMIT_STRING_SIZE+1]; }; and defined the following specializations: namespace boost { namespace mpl { template<typename T, T N> struct value_type<integral_c<T,N> > { typedef T type; }; template<typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6,typename T7,typename T8,typename T9, typename T10,typename T11> struct value_type<vector12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> > { typedef typename value_type<T0>::type type; }; } } Then we are able to use c_str on any sequence providing the specialization. Of course compile checking that the sequence size is not greater than BOOST_MPL_LIMIT_STRING_SIZE should be convenient. If I'm not wrong this change should not break working user code. Is there a possibility to add this trait to Boost.MPL and the corresponding specialization and move the c_str function to a standalone file ? Best, Vicente

On Sun, 07 Nov 2010 02:40:13 -0600, vicente.botet <vicente.botet@wanadoo.fr> wrote:
I have tried to add a value_type trait
template<typename Sequence> struct value_type { typedef typename Sequence::value_type type; };
changed the c_str to use the type trait
template<typename Sequence> struct c_str { typedef typename mpl::end<Sequence>::type iend; typedef typename mpl::begin<Sequence>::type i0; #define M0(z, n, data) \ typedef \ typename mpl::aux_::next_unless<BOOST_PP_CAT(i, n), iend>::type \ BOOST_PP_CAT(i, BOOST_PP_INC(n)); BOOST_PP_REPEAT(BOOST_MPL_LIMIT_STRING_SIZE, M0, ~) #undef M0
typedef c_str type; static typename value_type<Sequence>::type const value[BOOST_MPL_LIMIT_STRING_SIZE+1]; };
and defined the following specializations:
namespace boost { namespace mpl { template<typename T, T N> struct value_type<integral_c<T,N> > { typedef T type; }; template<typename T0,typename T1,typename T2,typename T3,typename T4, typename T5,typename T6,typename T7,typename T8,typename T9, typename T10,typename T11> struct value_type<vector12<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> > { typedef typename value_type<T0>::type type; }; } }
Then we are able to use c_str on any sequence providing the specialization. Of course compile checking that the sequence size is not greater than BOOST_MPL_LIMIT_STRING_SIZE should be convenient.
A more general approach would be something like this (untested): BOOST_MPL_HAS_XXX_TRAIT_DEF( value_type ) template< bool, typename X > struct value_type_impl { typedef typename X::value_type type; } template< typename X > struct value_type : value_type_impl< has_value_type<X>::value, X > { }; template< typename X > struct value_type_impl<false,X> { typedef typename value_type< typename front<X>::type >::type type; };
Is there a possibility to add this trait to Boost.MPL and the corresponding specialization and move the c_str function to a standalone file ?
If it's OK with Eric, I'd be happy to accept the patch. -- Aleksey Gurtovoy MetaCommunications Engineering

On 11/8/2010 5:06 AM, Aleksey Gurtovoy wrote:
On Sun, 07 Nov 2010 02:40:13 -0600, vicente.botet wrote: <snip>
Is there a possibility to add this trait to Boost.MPL and the corresponding specialization and move the c_str function to a standalone file ?
If it's OK with Eric, I'd be happy to accept the patch.
I have no opinion. It's your library. :-) -- Eric Niebler BoostPro Computing http://www.boostpro.com

----- Original Message ----- From: "Aleksey Gurtovoy" <agurtovoy@meta-comm.com> To: <boost@lists.boost.org> Sent: Monday, November 08, 2010 11:06 AM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
A more general approach would be something like this (untested):
BOOST_MPL_HAS_XXX_TRAIT_DEF( value_type )
template< bool, typename X > struct value_type_impl { typedef typename X::value_type type; }
template< typename X > struct value_type : value_type_impl< has_value_type<X>::value, X > { };
template< typename X > struct value_type_impl<false,X> { typedef typename value_type< typename front<X>::type >::type type; };
Yes this will be more general. I will add that as the sequence can be heterogeneous we would choose as value_type of a Integral Sequece wrapper as the common_type of all the element's value_type. If some of the Seq elements are not integral wrappers or there is not a common type, value_type<Seq> will not compile. A complementay possibility is to extend the c_str class with a new template parameter ValueType (all the sequence's member should be convertible to it). ValueType could default to Sequence::value_type or value_type<Sequence>. const char16_t* u16str = c_str<Seq, char16_t>::value; This will work if each element on Seq is convertible to char16_t. And the following will works as before const char* str = c_str<String>::value;
Is there a possibility to add this trait to Boost.MPL and the corresponding specialization and move the c_str function to a standalone file ?
If it's OK with Eric, I'd be happy to accept the patch.
I'll prepare a patch with the c_str parameter extension in a separated file, as it should not depend any more on mpl::string and could work with other sequences and the value_type trait in another file. Let me know if there is someting wrong. Best, Vicente

----- Original Message ----- From: "vicente.botet" <vicente.botet@wanadoo.fr> To: <boost@lists.boost.org> Sent: Monday, November 08, 2010 6:01 PM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
I'll prepare a patch with the c_str parameter extension in a separated file, as it should not depend any more on mpl::string and could work with other sequences and the value_type trait in another file. Let me know if there is someting wrong.
Hi, while trying to check c_str on set_c sequence I have found a behaviour that seems to a bug. With list_c, the following code works well, typedef mpl::list_c<char, 'a'> str_type; typedef mpl::begin<str_type>::type i0; typedef mpl::next<i0>::type i1; but with set_c typedef mpl::set_c<char, 'a'> str_type; typedef mpl::begin<str_type>::type i0; typedef mpl::next<i0>::type i1; I get the following compile error on gcc ../../../boost/mpl/set/aux_/iterator.hpp: In instantiation of `boost::mpl::next<boost::mpl::s_iter<main()::str_type, boost::mpl::set0_c<char> > >': ../../../boost/mpl/eval_if.hpp:38: instantiated from `boost::mpl::eval_if<boost::mpl::has_key<main()::str_type, mpl_::void_>, boost::mpl::identity<boost::mpl::s_iter<main()::str_type, boost::mpl::set0_c<char> > >, boost::mpl::next<boost::mpl::s_iter<main()::str_type, boost::mpl::set0_c<char> > > >' ../../../boost/mpl/set/aux_/iterator.hpp:38: instantiated from `boost::mpl::s_iter_get<main()::str_type, boost::mpl::set0_c<char> >' ../../../boost/mpl/set/aux_/iterator.hpp:57: instantiated from `boost::mpl::next<boost::mpl::s_iter<main()::str_type, boost::mpl::s_item<mpl_::integral_c<char, 'a'>, boost::mpl::set0_c<char> > > >' c_str\c_str_pass.cpp:271: instantiated from here or this one with msvc C:\cygwin\boost\v44\boost/mpl/set/aux_/iterator.hpp(56) : error C2039: 'base' : is not a member of 'boost::mpl::set0_c<T>' with [ T=char ] C:\cygwin\boost\v44\boost/mpl/eval_if.hpp(41) : see reference to class template instantiation 'boost::mpl::next<T>' being compiled with [ T=boost::mpl::s_iter<str_type,boost::mpl::set0_c<char>> ] C:\cygwin\boost\v44\boost/mpl/set/aux_/iterator.hpp(38) : see reference to class template instantiation 'boost::mpl::eval_if<C,F1,F2>' being compiled with [ C=boost::mpl::has_key<str_type,boost::mpl::set0<>::item_type_>, F1=boost::mpl::identity<boost::mpl::s_iter<str_type,boost::mpl::set0_c<char>>>, F2=boost::mpl::next<boost::mpl::s_iter<str_type,boost::mpl::set0_c<char>>> ] C:\cygwin\boost\v44\boost/mpl/set/aux_/iterator.hpp(57) : see reference to class template instantiation 'boost::mpl::s_iter_get<Set,Tail>' being compiled with [ Set=str_type, Tail=boost::mpl::set0_c<char> ] c_str\c_str_pass.cpp(271) : see reference to class template instantiation 'boost::mpl::next<T>' being compiled with [ T=boost::mpl::s_iter<str_type,boost::mpl::s_item<boost::mpl::integral_c<char,97>,boost::mpl::set0_c<char>>> ] BTW, this works also typedef mpl::set<mpl::char_<'a'> > str_type; typedef mpl::begin<str_type>::type i0; typedef mpl::next<i0>::type i1; What is happening? Am I missing something evident or is this a real bug? Best, Vicente

On 11/7/2010 2:38 AM, vicente.botet wrote:
I don't think I could find something in the doc that states that the push_back on a Integral Sequence Wrapper must be a Integral Sequence Wrapper, but I think that this is a desirable property.
Probably.
Do you have a workaround I can use to preserve it?
Sorry, no.
Do you think that it is possible to ensure that property without too much trouble inside the library?
I don't know. I wrote mpl::string and mpl::c_str, but I'm not mpl's maintainer. The problem you're describing has a very broad scope. I imagine all metafunctions that mutate sequences would need to be fixed. You'll need to take the issue up with Aleksey. I suggest filing a feature request ticket. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Sun, 07 Nov 2010 01:38:05 -0600, vicente.botet <vicente.botet@wanadoo.fr> wrote:
No push_back on a mpl::string is works as it is yet a Integral Sequence Wrapper. But push_back on a vector_c which is a Integral Sequence Wrapper is not a Integral Sequence Wrapper and this seems to me a more critical issue.
BOOST_STATIC_ASSERT((boost::is_same<hello2::value_type,char>::value)); // compile fail
I was loking for a way to represent static sequences of arbitrary chararcters types and mpl::string doesn't supports wchar_t, u16char or u32char so I though to move to vector_c.
BTW, I have found the use of c_str in a MPL tests string.cpp
typedef mpl::vector_c<char, 'a','b','c','d','e'> rgc; *** BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<rgc>::value)); typedef mpl::copy<rgc, mpl::back_inserter<mpl::string<> > >::type str; BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<str>::value));
I don't think I could find something in the doc that states that the push_back on a Integral Sequence Wrapper must be a Integral Sequence Wrapper, but I think that this is a desirable property.
It might seem so on the surface, but consider this: typedef push_back< rgc, long_<MAX_LONG> >::type v; or this: typedef push_back< rgc, struct my >::type v;
Do you have a workaround I can use to preserve it? Do you think that it is possible to ensure that property without too much trouble inside the library?
It's certainly possible, but it would also certainly complicate things. At the moment it seems to me to be too special of a case to be worth the trouble. -- Aleksey Gurtovoy MetaCommunications Engineering

----- Original Message ----- From: "Aleksey Gurtovoy" <agurtovoy@meta-comm.com> To: <boost@lists.boost.org> Sent: Monday, November 08, 2010 10:47 AM Subject: Re: [boost] [mpl] mpl::c_str fails for mpl::push_back
On Sun, 07 Nov 2010 01:38:05 -0600, vicente.botet <vicente.botet@wanadoo.fr> wrote:
No push_back on a mpl::string is works as it is yet a Integral Sequence Wrapper. But push_back on a vector_c which is a Integral Sequence Wrapper is not a Integral Sequence Wrapper and this seems to me a more critical issue.
BOOST_STATIC_ASSERT((boost::is_same<hello2::value_type,char>::value)); // compile fail
I was loking for a way to represent static sequences of arbitrary chararcters types and mpl::string doesn't supports wchar_t, u16char or u32char so I though to move to vector_c.
BTW, I have found the use of c_str in a MPL tests string.cpp
typedef mpl::vector_c<char, 'a','b','c','d','e'> rgc; *** BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<rgc>::value)); typedef mpl::copy<rgc, mpl::back_inserter<mpl::string<> > >::type str; BOOST_TEST(0 == std::strcmp("abcde", mpl::c_str<str>::value));
I don't think I could find something in the doc that states that the push_back on a Integral Sequence Wrapper must be a Integral Sequence Wrapper, but I think that this is a desirable property.
It might seem so on the surface, but consider this:
typedef push_back< rgc, long_<MAX_LONG> >::type v;
or this:
typedef push_back< rgc, struct my >::type v;
I see. I was thinking on homogeneous constainer and mpl sequences are by nature heterogeneous.
Do you have a workaround I can use to preserve it? Do you think that it is possible to ensure that property without too much trouble inside the library?
It's certainly possible, but it would also certainly complicate things. At the moment it seems to me to be too special of a case to be worth the trouble.
I understand. This would mean to have two families of sequences the current ones which are heretogeneus, and other that will accept some kind of hogeneity, but as you say this will complicat things too much. Thanks, Vicente
participants (3)
-
Aleksey Gurtovoy
-
Eric Niebler
-
vicente.botet