Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is C++ showing its age as programmers try to use it in ways it was never designed to be used?

Tags:

c++

Background

Using boost and other similar libraries is the easiest way to find compiler shortcomings, but is there a stage at which things go too far?

This mangled symbol:

_ZTSN5boost6spirit2qi6detail13parser_binderINS1_11alternativeINS_6fusion4consINS1_8sequenceINS6_INS1_16lexeme_directiveINS7_INS6_INS1_6actionINS1_9referenceIKNS1_4ruleIN9__gnu_cxx17__normal_iteratorIPKcSsEEFN7xxxxxxx2ir8carry_op2OpEvENS5_11unused_typeESM_EEEENS_7phoenix5actorINSQ_9compositeINSQ_11assign_evalENS5_6vectorINS0_14local_variableILi0EEENS0_8argumentILi0EEENS5_5void_ESZ_SZ_SZ_SZ_SZ_SZ_SZ_EEEEEEEENS6_INS1_10char_classINS0_3tag9char_codeINS15_5spaceENS0_13char_encoding5asciiEEEEENS5_3nilEEEEEEEEENS6_INS9_INS7_INS6_INSA_IKNSB_ISG_FSbIwSt11char_traitsIwESaIwEEvENSH_6parser11white_spaceISG_EESM_EEEENS6_INS1_12literal_charINS18_8standardELb1ELb0EEENS6_IS1R_NS6_IS1U_NS6_IS1R_NS6_IS1U_NS6_IS1R_NS6_IS1U_NS6_IS1R_S1C_EEEEEEEEEEEEEEEEEEEENSR_INSS_IST_NSU_INS0_9attributeILi0EEENSS_INSQ_6detail14construct_evalISJ_EENSU_ISW_SY_NSX_ILi1EEENSX_ILi2EEENSX_ILi3EEENSX_ILi4EEESZ_SZ_SZ_SZ_EEEESZ_SZ_SZ_SZ_SZ_SZ_SZ_SZ_EEEEEEEES1C_EEEEEENS6_INS7_INS6_IS1G_NS6_INS9_INS7_INS6_IS1R_NS6_IS1U_NS6_IS1R_NS6_IS1U_NS6_IS1R_NS6_IS1U_NS6_IS1U_S1W_EEEEEEEEEEEEEEEENSR_INSS_IST_NSU_IS26_NSS_IS29_NSU_ISW_SY_S2A_S2B_NSQ_5valueINS_8optionalIS1K_EEEES2C_SZ_SZ_SZ_SZ_EEEESZ_SZ_SZ_SZ_SZ_SZ_SZ_SZ_EEEEEEEES1C_EEEEEENS6_INS7_INS6_IS1G_NS6_INS9_INS7_IS21_EENSR_INSS_IST_NSU_IS26_NSS_IS29_NSU_ISW_SY_S2A_S2B_S2C_S2Y_SZ_SZ_SZ_SZ_EEEESZ_SZ_SZ_SZ_SZ_SZ_SZ_SZ_EEEEEEEES1C_EEEEEES1C_EEEEEEEEN4mpl_5bool_ILb0EEEEE

(1,388 characters)

Translates into (thanks c++filt!):

boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::lexeme_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, xxxxxxx::ir::carry_op::Op ()(), boost::fusion::unused_type, boost::fusion::unused_type> const>, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::local_variable<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > >, boost::fusion::cons<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::nil> > > > > > > > > >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::phoenix::composite<boost::phoenix::detail::construct_eval<xxxxxxx::ir::carry_op>, boost::fusion::vector<boost::spirit::local_variable<0>, boost::spirit::argument<0>, boost::spirit::argument<1>, boost::spirit::argument<2>, boost::spirit::argument<3>, boost::spirit::argument<4>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > >, boost::fusion::nil> > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::lexeme_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, xxxxxxx::ir::carry_op::Op ()(), boost::fusion::unused_type, boost::fusion::unused_type> const>, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::local_variable<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > >, boost::fusion::cons<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::nil> > > > > > > > > >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::phoenix::composite<boost::phoenix::detail::construct_eval<xxxxxxx::ir::carry_op>, boost::fusion::vector<boost::spirit::local_variable<0>, boost::spirit::argument<0>, boost::spirit::argument<1>, boost::spirit::argument<2>, boost::phoenix::value<boost::optional<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >, boost::spirit::argument<3>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > >, boost::fusion::nil> > >, boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::lexeme_directive<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, xxxxxxx::ir::carry_op::Op ()(), boost::fusion::unused_type, boost::fusion::unused_type> const>, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::local_variable<0>, boost::spirit::argument<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > >, boost::fusion::cons<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, boost::fusion::nil> > > >, boost::fusion::cons<boost::spirit::qi::action<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > ()(), xxxxxxx::parser::white_space<__gnu_cxx::__normal_iterator<char const*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, boost::fusion::unused_type> const>, boost::fusion::nil> > > > > > > >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, boost::fusion::vector<boost::spirit::attribute<0>, boost::phoenix::composite<boost::phoenix::detail::construct_eval<xxxxxxx::ir::carry_op>, boost::fusion::vector<boost::spirit::local_variable<0>, boost::spirit::argument<0>, boost::spirit::argument<1>, boost::spirit::argument<2>, boost::spirit::argument<3>, boost::phoenix::value<boost::optional<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > > >, boost::fusion::nil> > >, boost::fusion::nil> > > >, mpl_::bool_<false> >

(12,980 characters)


Question

So my question is, in light of these (which technically don't pass the standard as I understand it, as the mangled name is over 1,024 characters), is this a sign that C++ is showing its age by not keeping up-to-date with the newest concepts? Or is it simply a sign that programmers are expecting too much from the language, and template libraries like boost are doing the best they can to facilitate this?

like image 703
Matthew Iselin Avatar asked Sep 03 '09 10:09

Matthew Iselin


8 Answers

Wouldn't the language be showing its age if people did not apply it to new, bigger problems than originally intended?

I think this is exactly the opposite -- it shows that C++ is able to do something far more complex than was intended in the earliest versions of the language. How is that "showing its age"? C++ would be showing its age if it was still being used in the half-baked Java-like OOP style popular 15 years ago.

I think the fact that the usage of the language continues to evolve so much, even when the actual standard is unchanged, is a sign of strength.

Of course, C++ is showing its age in countless other ways, but I don't think this is one of them. On the contrary, this is one of C++'s redeeming features.

like image 150
jalf Avatar answered Oct 04 '22 09:10

jalf


I think the fact that people keep coming up with new ways of using the features of C++ is the sign of its flexibility and power, not its aging.

like image 24
Dima Avatar answered Oct 04 '22 11:10

Dima


In C++, the mangled symbol name is the equivalent of the call stack in other languages.

Show a 1970s asm programmer a call stack 23 deep, and they would say 'surely that is taking that new-fangled function stuff a bit far? How could you possibly debug and analyse something that complicated? You would need a special tool just to work out where everything was in memory'.

In fact, in the absence of a debugger, it would actually be really impractical to work with functions nested that deep - fine when things work, but when they break, it becomes impossibly complex to relate the memory image back to your code.

Eclipse CDT actually has a really nice feature where it can take pre-processor macros and expand them one step at a time, with backwards and forwards buttons. Display of templates, especially in error messages, needs something like that. So you can navigate between

list<T>
list<ptr<t>>
list<ptr<string<T>>>>

and so on.

like image 20
soru Avatar answered Oct 04 '22 09:10

soru


I think it's a sign of aging for the standard limiting mangled name to 1,024 characters ;-)

like image 28
Michael Krelin - hacker Avatar answered Oct 04 '22 11:10

Michael Krelin - hacker


As much as a wrench shows its age when it's being used to hammer in a nail.

like image 28
databyss Avatar answered Oct 04 '22 10:10

databyss


I don't think the example you have given is a good example of the language being used "in ways it was never designed to be used". C++'s design explicitly allows for uses such as this. I think what it really shows is some of the language's weaknesses. The way templates and static typing work together in the language result in monstrosities such as your nice example. Even simpler uses of templates can easily result in absurdly long and complicated names. Programmers more familiar with other languages and less familiar with C++ would see things like this and immediately recognize that there's something not quite "right" with C++.

Now it's not to say that C++ is a crap language just because it has some shortcomings. All languages that I've ever used have some disadvantages. In the end, I think your example illustrates one of C++'s weaknesses better than it illustrates C++'s age.

like image 42
Dan Moulding Avatar answered Oct 04 '22 09:10

Dan Moulding


Most of the resulting name is "noise", in that it's either specified by a typedef, or the arguments were defaults.

This IMHO, is more of an issue with where compiler implementors have decided to focus their efforts. Most compiler vendors spend more of their time ensuring that they implement the (complex) C++ standard correctly in a way that produces code that is as fast as they can possibly make it.

Providing pretty names for most is an after thought to the above.

Just to highlight this, with the exception of the last two items, the following mappings could be implemented in the demangler so that they always took place:

  • We can search and replace basic_string<const char *, ...> and replace it with string
  • We can search and replace basic_string<const wchar_t *, ...> and replace it with wstring
  • We can search and replace __gnu_cxx::__normal_iterator<char const *... and replace it with string::const_iterator
  • For display purposes we can remove boost::<namespace>:: and std:: as in context these don't add much.
  • Finally, C++ 0x will introduce template parameter packs and so we can remove things like boost:fusion::void_, boost:fusion::void_, boost:fusion::void_, since there will no longer be any need for preprocessor hacks to handle them.

After all of the above we have:

qi::detail::parser_binder<qi::alternative<cons<qi::sequence<cons<qi::lexeme_directive<qi::sequence<cons<qi::action<qi::reference<qi::rule<string::const_iterator, xxxxxxx::ir::carry_op::Op ()(), unused_type, unused_type> const>, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, vector<local_variable<0>, argument<0> > > > >, cons<qi::char_class<tag::char_code<tag::space, char_encoding::ascii> > > > > >, cons<qi::action<qi::sequence<cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const> > > > > > > > > > >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, vector<attribute<0>, boost::phoenix::composite<boost::phoenix::detail::construct_eval<xxxxxxx::ir::carry_op>, vector<local_variable<0>, argument<0>, argument<1>, argument<2>, argument<3>, argument<4> > > > > > > > > >, cons<qi::sequence<cons<qi::lexeme_directive<qi::sequence<cons<qi::action<qi::reference<qi::rule<string::const_iterator, xxxxxxx::ir::carry_op::Op ()(), unused_type, unused_type> const>, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, vector<local_variable<0>, argument<0> > > > >, cons<qi::char_class<tag::char_code<tag::space, char_encoding::ascii> > > > > >, cons<qi::action<qi::sequence<cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const> > > > > > > > > > >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, vector<attribute<0>, boost::phoenix::composite<boost::phoenix::detail::construct_eval<xxxxxxx::ir::carry_op>, vector<local_variable<0>, argument<0>, argument<1>, argument<2>, boost::phoenix::value<boost::optional<wstring> >, argument<3> > > > > > > > > >, cons<qi::sequence<cons<qi::lexeme_directive<qi::sequence<cons<qi::action<qi::reference<qi::rule<string::const_iterator, xxxxxxx::ir::carry_op::Op ()(), unused_type, unused_type> const>, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, vector<local_variable<0>, argument<0> > > > >, cons<qi::char_class<tag::char_code<tag::space, char_encoding::ascii> > > > > >, cons<qi::action<qi::sequence<cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const>, cons<qi::literal_char<char_encoding::standard, true, false>, cons<qi::reference<qi::rule<string::const_iterator, wstring()(), xxxxxxx::parser::white_space<string::const_iterator >, unused_type> const> > > > > > > > >, boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::assign_eval, vector<attribute<0>, boost::phoenix::composite<boost::phoenix::detail::construct_eval<xxxxxxx::ir::carry_op>, vector<local_variable<0>, argument<0>, argument<1>, argument<2>, argument<3>, boost::phoenix::value<boost::optional<wstring> > > > > > > > > > > > > > >, mpl_::bool_<false> >

This string now has 5k characters (still a lot I agree) but its now less than half of the lenght of the original. Looking deeper at a sub section other patterns are visible:

cons<qi::reference<qi::rule<string::const_iterator, wstring()()
      , xxxxxxx::parser::white_space<string::const_iterator >
      , unused_type> const>
      , cons<qi::literal_char<char_encoding::standard, true, false>,
cons<qi::reference<qi::rule<string::const_iterator, wstring()()
      , xxxxxxx::parser::white_space<string::const_iterator >
      , unused_type> const>
      , cons<qi::literal_char<char_encoding::standard, true, false>,
cons<qi::reference<qi::rule<string::const_iterator, wstring()()
      , xxxxxxx::parser::white_space<string::const_iterator >
      , unused_type> const>
      , cons<qi::literal_char<char_encoding::standard, true, false>,
cons<qi::reference<qi::rule<string::const_iterator, wstring()()
      , xxxxxxx::parser::white_space<string::const_iterator >
      , unused_type> const>
      , cons<qi::literal_char<char_encoding::standard, true, false>,
cons<qi::reference<qi::rule<string::const_iterator, wstring()()
      , xxxxxxx::parser::white_space<string::const_iterator >
      , unused_type> const>

Again, 'boost' is using preprocessor tricks to allow a type to be built as if it is a vector. Similar to the case of void_ and nil, C++-0x parameter packs will avoid the need for the preprocessor to expand everything out 10 deep and the templates will be built to hold exactly what the user required. The above string takes up nearly a 1000 characters, and it is just one of 3 or 4 such strings in the original.

So if the question is: Is C++'03 showing its age, then the answer is "maybe" but only because it doesn't yet have template parameter packs.

like image 24
Richard Corden Avatar answered Oct 04 '22 11:10

Richard Corden


C was designed in the spirit of "mechanism, not policy"; this means it can cope in strange places, like embedded devices or kernels, where a decent standard library may not be present. It opens up the door to writing portable code (though doesn't by any means guarantee it). Importantly, the language is powerful enough that important things are not treated as special cases (e.g. "printf" is just another function; you don't need special operators to do string formatting or any such). This means that the language can (to some extent) be built by its users, not its creators.

C++ has inherited some of this spirit. And in this spirit, people have made libraries that offer both functionality and fairly succinct syntax.

C++ is still used in cheap embedded systems because it cuts the costs of software development compared to C, but remains reasonably fast (and has actually been ported to the systems). For such reasons I don't think C++ is broken or showing its age.

But trying to turn it into a language suitable for "modern" pursuits is a simple case of using the wrong tool for the job. C++ has a place, but it is taking up a much wider area than it should be due to its historical popularity and momentum.

like image 22
Artelius Avatar answered Oct 04 '22 10:10

Artelius