Skip to main content
GameDev.net gamedev.net
🔒 Locked

Why do [some] people end up despising c++? limits of c++?

Started by IFooBar Oct 10, 2006 at 5:30 PM 52 replies 10.9k views
Original Post
IFooBar
IFooBar
Just curious, what are the things that make so many people who have been using the language for so long start to hate it? From how far my studies are taking me it seems like c++ has no end, you can do anything with it. Especially with the addition of libraries like boost and the support for multiple paradigms and the now new support for even more programming paradigms (meta programming and functional programming come to mind) I'm not looking for excuses like "I don't like c++ because of things like type> - you need to put a space between the > > or you get a compiler error" because something like that represents lack of knowledge/experience or the fact that you're human and you can make a mistake. But it's caught at compile time and can be easily fixed. I mostly hear about small things like this - ie: syntactical complaints. I've also heard a lot of people say it's because they much prefer managed languages. I'm assuming that most people when they say "managed" they mean "automatic memory management". Now as far as I know you can add a GC to c++ (I remember seeing a non-intrusive garbage collector for c++ available somewhere but can't remember, or maybe I'm mistaken). And there are many facilities available like the smart pointer library in boost. I'm not saying that there's no need for managed languages, of course having a GC out of the box and directly supported by the language makes things much cleaner and simpler... but it's not *that* big a deal is it? (the big a deal as in the process of taking care of memory in c++ using either smart pointers, and/or the GC lib I vaguely mentioned) I've been using c++ for a while now (a solid 5 years at the least), and I still learn new possibilities/idioms/functionalities/techniques/etc that are enabled either directly or indirectly by c++ (I've read that template metaprogramming was a complete fluke for example) And a while back I discovered FC++ (functional c++, which is I think making its way into boost along side that so pretty lambda). But I havent had extensive use of c++ commercially, so that's probably one of the main problems in my lack of knowledge here. And plus, most of the people that I've seen mention hating c++ are industry veterans. The hobby people stay away from c++ (i'm not saying this is the rule) because other languages are easier to start with. It's the veterans reasons for hating c++ that I'm mostly interested in... I suppose I'm asking for c++'s limits (plus a little bit extra). Is it mostly the little "gotchas" that make c++ a PITA or is there something more? Is it simply that c++ is just too big to master, and most people just get fedup of trying? Also, found a sneak peak into c++0x and one of their goals is to make the thing easier for novices (details in that link). And there's mention of threading and a built in GC and they even mention the >> versus > > issue :) Comments?
[size=2]aliak.net
kuphryn
kuphryn
as you look at low-level development tools, you see there are more options. c is even more flexible than c++, but you would have to design your own parser and compiler. same with assembly. c++ has its limitations. and any future revisions of c++ will have limitations. thats what makes software development exciting.

Kuphryn
BLiTZWiNG
BLiTZWiNG
Well I programmed in asm, then Pascal, then C++ for a number of years before I was introduced to web programming, then took on C# for the last 5 years professionally. I never did C++ professionally, but I can tell you why I don't like it, and you probably wont like my reasons.

1. Header files.
I hate them. They cause problems unless you know what you're doing and plan carefully for them. AFAIK, they were only made because IDEs of old can't do what IDEs of today can with the likes of C#. So while they may have been a good idea when they were made, they are now antiquated.

2. ->
Yeap. C++ is meant to be the master of saving key strokes, but that is 3 keys. I'm no expert, but 99% of my objects are dynamically allocated, and -> makes it painful.

3. Microsoft.
I am a bit of an M$ fan boi, I will admit that, but some of the crap that write is so mind boggling it makes me sick. The macro definitions they have in place when you start up an MFC app for instance, I could spend 50 years tracing into a single macro to find out that it just redefines a type...

Anyway, those are the main gripes I have. They are petty and small, but sometimes its the small things that count. C++ is just extension after extension to a very old language, and for simple non-gui stuff, its fine (for me). I am hooked on C#, so I am biased, but I did use C++ for many years while playing with DirectX.

As always, this is just my opinion, and you can flame me all you like.
DrEvil
DrEvil
My biggest c++ gripe is header files. I wish they could make changes to eliminate them. Biggest waste of time in development is the c++ compilation system, which is mostly because of header files.
IFooBar
IFooBar
Quote:
Original post by BLiTZWiNG
I never did C++ professionally, but I can tell you why I don't like it, and you probably wont like my reasons.


I didnt make this post to start an argument or make judgements or anything, I won't say anything about your reasons, I just want to be more aware that's all (note this was not really directed at you per-se, but generally to whoever partisipates in this thread)

[size=2]aliak.net
coderx75
coderx75
Seems kinda lounge-ish but I'll bite.

First, I think a lot of people have been disappointed by the OOP hype. The Object-Oriented aspects of the language were supposed to be a superior method of software architecture. When programmers attempt it and find that things don't piece together as expected, they get disouraged. The answer to this: design patterns. However, like all "answers" to C++'s shortcomings, it seems more like a bandaid.

Second, a lot of newer "standards" for C++ seem like just that: bandaids. Templates, design patterns (not so much a standard as a principle), boost (may soon be standardized), etc. have all become the usual practice for getting around C++'s problems. Java and C#, on the other hand, have addressed many of the issues.

Third, and most important, development time. We have computers with massive amounts of power. I'm at work at the moment typing this on a system with Dual 2.8GHz Xeons, each Dual Core and each core with Hyperthreading. Don't even get me started on our servers. Do I REALLY need to squeeze every ounce of performance out of an application by using C++? [headshake] So, why am I going to tell my boss that we are going to go over budget with the current project when I can do it in half the time (or better) with C#? That's no way to secure employment.

I don't hate C++. That'd be like saying I hate assembly language. It was good for its purpose at the time but just isn't feasible in the present. Now, C++ still has its place but the advantages of using it are becoming fewer and fewer. I still think it's a good language to learn. Working with the restrictions of C++ and then moving to C# made me really appreciate the language.
Quit screwin' around! - Brock Samson
BLiTZWiNG
BLiTZWiNG
Quote:
Original post by IFooBar
Quote:
Original post by BLiTZWiNG
I never did C++ professionally, but I can tell you why I don't like it, and you probably wont like my reasons.


I didnt make this post to start an argument or make judgements or anything, I won't say anything about your reasons, I just want to be more aware that's all (note this was not really directed at you per-se, but generally to whoever partisipates in this thread)


Sorry my post wasn't meant to come out snappy and all defensive like you were taking a stab at me..

I think I wrote it like that because I don't believe that C++ is limited in power at all. It can pretty much do everything, and I think if there is a reason why someone has moved on to Java or C#, it is because more than one language can do what needs to be done, and thus the language with less tedium is chosen. I can't imagine the headaches I'd get if I tried to write a web app using C++.
Extrarius
Extrarius
I think that most of the time, when people say they prefer "managed" languages, they _DON'T_ mean languages with garbage collection. I think that what they generally mean is 'complete' languages that have libraries covering all the main topics application development generally touches on, such as GUI development, networking, and other such tasks that are not dealt with at all by lower level languages like C++. Yes, you can find libraries to do anything in C++, but the fact that you have a choice between third party libraries instead of having a first-party product shoved in your face means there is probably less documentation, half the documentation will be about libraries you didn't pick, etc.

The main reason I don't like C++ is that it's metaprogramming capabilities are practically non-existant. Sure, you can do all kinds of fancy tricks to evaluate some things at compile time, but you have no guarantee that the compiler will full evaluate them or emit an error (and I've made programs that successfully compile {without warnings even} to incorrect code on MSVS 2003 because they exceed the template recursion limit) and the code will be practically unreadable. God help anybody that tries to maintain it, especially once they cause an error related to the templates (which would likely cause an error message that mentions a class hidden 5+ 'detail levels' deep in a large heirarchy).

Quote:
Original post by IFooBar
[...]it seems like c++ has no end, you can do anything with it.[...]
You can do anything[1] with a universal turing machine, but good luck writing any real application on such a beast.

In language wars, the actual computing power of a language is meaningless, because any decent languages are equal in that reguard. What differs is the expressivity - the ability to convert the programmer's intent into the symbols that make up the language.

For example: with assembly language, the expressivity is very limited because the language doesn't provide ways to 'say' high-level things like inheritence or polymorphism. You could still implement the exact same functionality that high-level languages provide, but your code would be more difficult to read because the language doesn't have 'words' to directly 'say' what you want to 'say'.

On the other hand, C++ has a decent number of words to express high-level concepts such as polymorphism and inheritence, so you can abstract fairly well, but it lacks higher-level concepts like first-class functions, first-class classes, and metaprogramming, so some things can still be very difficult to implement in a clean, readable, elegant way.

[1] Well, anything deterministically computable.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
load_bitmap_file
load_bitmap_file
Quote:
Original post by IFooBar
Just curious, what are the things that make so many people who have been using the language for so long start to hate it? From how far my studies are taking me it seems like c++ has no end, you can do anything with it. Especially with the addition of libraries like boost and the support for multiple paradigms and the now new support for even more programming paradigms (meta programming and functional programming come to mind)

I'm not looking for excuses like

"I don't like c++ because of things like type> - you need to put a space between the > > or you get a compiler error"

because something like that represents lack of knowledge/experience or the fact that you're human and you can make a mistake. But it's caught at compile time and can be easily fixed. I mostly hear about small things like this - ie: syntactical complaints. I've also heard a lot of people say it's because they much prefer managed languages. I'm assuming that most people when they say "managed" they mean "automatic memory management".

Now as far as I know you can add a GC to c++ (I remember seeing a non-intrusive garbage collector for c++ available somewhere but can't remember, or maybe I'm mistaken). And there are many facilities available like the smart pointer library in boost. I'm not saying that there's no need for managed languages, of course having a GC out of the box and directly supported by the language makes things much cleaner and simpler... but it's not *that* big a deal is it? (the big a deal as in the process of taking care of memory in c++ using either smart pointers, and/or the GC lib I vaguely mentioned)

I've been using c++ for a while now (a solid 5 years at the least), and I still learn new possibilities/idioms/functionalities/techniques/etc that are enabled either directly or indirectly by c++ (I've read that template metaprogramming was a complete fluke for example) And a while back I discovered FC++ (functional c++, which is I think making its way into boost along side that so pretty lambda). But I havent had extensive use of c++ commercially, so that's probably one of the main problems in my lack of knowledge here. And plus, most of the people that I've seen mention hating c++ are industry veterans. The hobby people stay away from c++ (i'm not saying this is the rule) because other languages are easier to start with. It's the veterans reasons for hating c++ that I'm mostly interested in...

I suppose I'm asking for c++'s limits (plus a little bit extra). Is it mostly the little "gotchas" that make c++ a PITA or is there something more? Is it simply that c++ is just too big to master, and most people just get fedup of trying?

Also, found a sneak peak into c++0x and one of their goals is to make the thing easier for novices (details in that link). And there's mention of threading and a built in GC and they even mention the >> versus > > issue :)

Comments?


I'd say people start disliking C++ once they start using other languages and realize there are a lot of useful programming "structures" not available or cumbersome to use in C++. I stopped thinking C++ was teh best evar when two things happened: 1. I was working on a largish C++ project for some time, and 2. I learned Python.

Regarding 1., I think everybody learning C++ at one point or another realizes that the language is really dang complex, and there are an amazing number of subtle cases where things do not work as you would expect. I used to think that most of these special cases would only pop up in esoteric situations but that really isn't true. Stuff like static initialization order, RAII, non-virtual member function calls in a derived class's constructor and etc. pop up all over the place when you're working on a decently sized project. Then stuff like having to constantly deal with header files, linking libs, hunting down memory leaks and whatnot gets tiring quickly.

Regarding 2., it probably doesn't make much sense to compare Python directly to C++, but as a language Python is just so... elegant in comparison. I'll probably botch it up trying to explain, so I'll just point in the general direction of the documentation if you're interested. Learning new languages broadens your insight into the world of programming.

So I guess to summarize, yes, C++ is a powerful language, but it's not especially "nice" to work with, and IMO the people who really love it haven't really used any other languages much yet.
Telastyn
Telastyn
Quote:

because something like that represents lack of knowledge/experience or the fact that you're human and you can make a mistake.


The key principle to other (better) languages is that they make it so you need far less knowledge (by being more consistant, being more intuitive, having a syntax which more easily facilitates IDE helping tools) and are far less likely to make a mistake.

Further, C++ is the king of undefined behavior. Often you don't realise you've made a mistake. Some poor sap maintaining your code years later makes a subtle change or changes the underlying system causing catastrophic failure. Hurray.

The problem with C++ in practical terms is that even if the improvements you list help (and they do in most cases), they either:

- aren't supported by the working environment.
- are not worth the time and effort to make old code work in a new environment.
- lose most of their benefits when working with existing code (which takes bald pointers, char *'s)

And that ignores the fact that all the other 'wrong' ways exist and are taught by almost every C++ book in existance.

And yes, having a GC does make *that* big a deal.
PhilMorton
PhilMorton
Offtopic kinda, but, I like C++ because it doesnt have GC.

Relying on GC makes for baaad code IMO.

Better to force yourself to think about when a resource is no longer needed, instead of just treating memory allocation with contempt.

But im sure many will disagree and say that not having to think about what you're doing makes development much faster ;P

(In case you didnt get the subtle sarcasm, im just making a cheap jab at inexperienced C#/Java programmers)
Allways question authority......unless you're on GameDev.net, then it will hurt your rating very badly so just shut the fuck up.
Fruny
Fruny
Quote:
Original post by Extrarius
I think that most of the time, when people say they prefer "managed" languages, they _DON'T_ mean languages with garbage collection. I think that what they generally mean is 'complete' languages that have libraries covering all the main topics application development generally touches on, such as GUI development, networking, and other such tasks that are not dealt with at all by lower level languages like C++.


Quoted for truth.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
MaulingMonkey
MaulingMonkey
I will demonstrate with a metaprogramming example.


Let's take a look at an uber generic factory class in C++, designed to have nice usage syntax. Probably took about a week or two of full blown programming for me to write, debug, and get running on both GCC and VS2k5 (latest versions, which generated so many errors on GCC when it had run fine on VS at first that I created a script to auto-open a seperate text viewer for the error log, which was big enough that it (the viewer) truncated the list at around 128k until I explicitly told it to go beyond that limit):

// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// Jun 17, 2006 - Added key to template param list (compatibility break!)// May 31, 2006 - Created#ifndef BOOST_PP_IS_ITERATING  #ifndef IG_INDUSTRY_FACTORY_DETAIL_ASPECT  #define IG_INDUSTRY_FACTORY_DETAIL_ASPECT    #include "industry.factory.exception.hpp"    #include "industry.type.hpp"    #include <boost/preprocessor/iteration.hpp>    #include <boost/preprocessor/repetition.hpp>namespace industry {	namespace factory_detail {		template < typename Base , typename Method > class factory_aspect;				#define BOOST_PP_ITERATION_LIMITS   (0,INDUSTRY_METHOD_ARGUMENTS_LIMIT)		#define BOOST_PP_FILENAME_1         "industry.factory.detail.aspect.hpp"		#include BOOST_PP_ITERATE()	}}  #endif //ndef IG_INDUSTRY_FACTORY_DETAIL_ASPECT#else //BOOST_PP_IS_ITERATING#define N                      BOOST_PP_ITERATION()#if N == 0  #define TRAILING_TYPENAME_AN  #define AN                     void  #define TRAILING_A_ARGN  #define ARGN#else  #define TRAILING_TYPENAME_AN   BOOST_PP_ENUM_TRAILING_PARAMS(N,typename A)  #define AN                     BOOST_PP_ENUM_PARAMS(N,A)  #define TRAILING_A_ARGN        BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N,A,arg)  #define ARGN                   BOOST_PP_ENUM_PARAMS(N,arg)#endif		template < typename KeyT , typename Interface , typename Methods   TRAILING_TYPENAME_AN >		class factory_aspect< factory_base< KeyT , Interface , Methods > , void ( AN ) > {			typedef Interface                                                             interface_type;			typedef factory_base< KeyT , Interface , Methods >                            base_type;			typedef typename interface_type::template method< void ( AN ) >::return_type  return_type;			typedef typename interface_type::template method< void ( AN ) >::type         method_type;			typedef method_type *                                                         method_ptr_type;		public:			return_type create( KeyT key  TRAILING_A_ARGN ) {				base_type & self = static_cast< base_type & >( *this );				if ( !self.tables[ key ] ) throw bad_factory_type();				return (*(static_cast< method_ptr_type >( self.tables[ key ]->entries)))( ARGN );			}		};		#undef N#undef TRAILING_TYPENAME_AN#undef AN#undef TRAILING_A_ARGN#undef ARGN#endif //BOOST_PP_IS_ITERATING


// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// Jun 17, 2006 - Switched to file iteration// May 31, 2006 - industry.factory.any => industry.factory.detail.base// May 31, 2006 - Parred down to main and aspect specializations// May ??, 2006 - Slowly generalized classes & deleted their defunct versions// May 21, 2006 - Created#ifndef BOOST_PP_IS_ITERATING  #ifndef IG_INDUSTRY_FACTORY_DETAIL_BASE  #define IG_INDUSTRY_FACTORY_DETAIL_BASE    #include "industry.config.hpp"    #include "industry.factory.hpp"    #include "industry.factory.detail.aspect.hpp"    #include "industry.factory.detail.coerce.methods.hpp"    #include "industry.factory.detail.vtable.hpp"    #include "industry.factory.interface.aspects.hpp"    #include "industry.methods.hpp"    #include "industry.inherit.hpp"    #include "industry.multitype.hpp"    #include "industry.type.hpp"    #include <boost/any.hpp>    #include <boost/preprocessor/iteration.hpp>    #include <boost/preprocessor/repetition.hpp>    #include <map>    #include <cassert>    #define INDUSTRY_FACTORY_ASPECT_CREATE_use(z,n,limit) 		using factory_detail::factory_aspect< factory_base< key_type , Interface , methods< BOOST_PP_ENUM_PARAMS(limit,M) > > , M ## n >::create;        #define BOOST_PP_ITERATION_LIMITS (1,INDUSTRY_METHODS_LIMIT)    #define BOOST_PP_FILENAME_1 "industry.factory.detail.base.hpp"    #include BOOST_PP_ITERATE()        #undef INDUSTRY_FACTORY_ASPECT_CREATE_use  #endif //ndef IG_INDUSTRY_FACTORY_DETAIL_BASE#else //BOOST_PP_IS_ITERATING#define N             BOOST_PP_ITERATION()#define TYPENAME_Mn   BOOST_PP_ENUM_PARAMS(N,typename M)#define Mn            BOOST_PP_ENUM_PARAMS(N,M)namespace industry {	template < typename KeyT , typename Interface , TYPENAME_Mn >	class factory_base< KeyT , Interface , methods< Mn > >		: public crtp_template_inherit< factory_detail::factory_aspect ,		         factory_base< KeyT , Interface , methods< Mn > > , Mn >	{		typedef KeyT                                                                           key_type;		typedef Interface                                                                      interface_type;		typedef methods< Mn >                                                                  raw_methods_type;		typedef typename factory_detail::coerce_methods< Interface , raw_methods_type >::type  methods_type;		typedef factory_detail::vtable< methods_type >                                         vtable_type;		template < typename , typename > friend class factory_detail::factory_aspect;		std::map< key_type , vtable_type * > tables;	public:		BOOST_PP_REPEAT(n,INDUSTRY_FACTORY_ASPECT_CREATE_use,N)		template < typename T > void type( key_type key ) {			if ( tables[ key ] ) return;			tables[ key ] = vtable_type::template create< interface_type::template aspect , T >();		}	};		template < typename Interface , TYPENAME_Mn >	class factory_base< industry::type , Interface , methods< Mn > >		: public crtp_template_inherit< factory_detail::factory_aspect ,		         factory_base< industry::type , Interface , methods< Mn > > , Mn >	{		typedef industry::type                                                                 key_type;		typedef Interface                                                                      interface_type;		typedef methods< Mn >                                                                  raw_methods_type;		typedef typename factory_detail::coerce_methods< Interface , raw_methods_type >::type  methods_type;		typedef factory_detail::vtable< methods_type >                                         vtable_type;		template < typename , typename > friend class factory_detail::factory_aspect;		std::map< key_type , vtable_type * > tables;	public:		BOOST_PP_REPEAT(n,INDUSTRY_FACTORY_ASPECT_CREATE_use,N)		template < typename T > void type( key_type key ) {			if ( tables[ key ] ) return;			tables[ key ] = vtable_type::template create< interface_type::template aspect , T >();		}		template < typename T > void auto_type() {			if ( tables[ typeid(T) ] ) return;			tables[ typeid(T) ] = vtable_type::template create< interface_type::template aspect , T >();		}	};}#endif //BOOST_PP_IS_ITERATING


// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// May 31, 2006 - Created#ifndef BOOST_PP_IS_ITERATING  #ifndef IG_INDUSTRY_FACTORY_DETAIL_COERCE_METHODS  #define IG_INDUSTRY_FACTORY_DETAIL_COERCE_METHODS  #include <boost/preprocessor/repetition.hpp>  #include <boost/preprocessor/iteration.hpp>  #include "industry.config.hpp"  #include "industry.methods.hpp"  #include "industry.multitype.hpp"namespace industry {	namespace factory_detail {		template < typename Interface , typename Methods > struct coerce_methods;				#define BOOST_PP_ITERATION_LIMITS (1,INDUSTRY_METHODS_LIMIT)		#define BOOST_PP_FILENAME_1 "industry.factory.detail.coerce.methods.hpp"		#include BOOST_PP_ITERATE()	}}  #endif //ndef IG_INDUSTRY_FACTORY_ASPECT#else //BOOST_PP_IS_ITERATING  #define N                              BOOST_PP_ITERATION()  #define TYPENAME_MN                    BOOST_PP_ENUM_PARAMS(N,typename M)  #define MN                             BOOST_PP_ENUM_PARAMS(N,M)  #define VTABLE_FPTR_entry(z,n,unused)  typename Interface::template method< M ## n >::type  #define VTABLE_FPTRN                   BOOST_PP_ENUM(N,VTABLE_FPTR_entry,~)		template < typename Interface , TYPENAME_MN >		struct coerce_methods< Interface , methods< MN > > {			typedef methods< VTABLE_FPTRN > type;		};  #undef N  #undef TYPENAME_MN  #undef MN  #undef VTABLE_FPTR_entry  #undef VTABLE_FPTRN#endif //ndef IG_INDUSTRY_FACTORY_DETAIL_COERCE_METHODS


// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// May 31, 2006 - Switched to file iteration// May 27, 2006 - Created#ifndef BOOST_PP_IS_ITERATING  #ifndef IG_INDUSTRY_FACTORY_DETAIL_VTABLE  #define IG_INDUSTRY_FACTORY_DETAIL_VTABLE    #include <boost/preprocessor/repetition.hpp>    #include <boost/preprocessor/iteration.hpp>	#include "industry.config.hpp"namespace industry {	namespace factory_detail {		template < typename Methods > struct vtable;				#define BOOST_PP_ITERATION_LIMITS  (1, INDUSTRY_METHODS_LIMIT)		#define BOOST_PP_FILENAME_1        "industry.factory.detail.vtable.hpp"		#include BOOST_PP_ITERATE()	}}  #endif //ndef IG_INDUSTRY_FACTORY_DETAIL_VTABLE#else // BOOST_PP_IS_ITERATING#define n BOOST_PP_ITERATION()#define TYPENAME_Mn               BOOST_PP_ENUM_PARAMS( n , typename M )#define Mn                        BOOST_PP_ENUM_PARAMS( n , M )#define MPTR_impl(z,n,unused)     M ## n *#define MPTRn                     BOOST_PP_ENUM( n , MPTR_impl , ~ )#define VTABLE_entry(z,n,unused)  table.entries = & Aspect< T , M ## n >::create		template < TYPENAME_Mn > struct vtable< methods< Mn > > {			multitype< MPTRn > entries;				template < template < typename , typename > class Aspect , typename T >			static vtable * create( void ) {				static vtable table;				BOOST_PP_ENUM(n, VTABLE_entry , ~);				return &table			}		};#undef TYPENAME_Mn#undef Mn#undef MPTRn#undef MPTR_impl#undef VTABLE_entry#endif //ndef BOOST_PP_IS_ITERATING


// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// May 31, 2006 - invalid_factory_type => bad_factory_type, implemented thrower// May 27, 2006 - Created#ifndef IG_INDUSTRY_FACTORY_EXCEPTION#define IG_INDUSTRY_FACTORY_EXCEPTION#include <exception>namespace industry {	struct bad_factory_type : std::exception {		//thown by:   factory::create( id , ... )		//thown when: there was no call to factory::type< T >() with typeid(T) == id		bad_factory_type() throw() {}		~bad_factory_type() throw() {}		const char * what( void ) const throw() {			return "Invalid factory type";		}	};}#endif //ndef IG_INDUSTRY_FACTORY_EXCEPTION


// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// Jun 17, 2006 - Added key to template param list (compatibility break!)// May 27, 2006 - Changed factory to factory_base, new factory allows more syntax & interface options// May 21, 2006 - Created#ifndef IG_INDUSTRY_FACTORY#define IG_INDUSTRY_FACTORY#ifndef INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMIT#define INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMIT INDUSTRY_METHOD_ARGUMENTS_LIMIT#endif //ndef INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMITnamespace industry {	template < typename T > struct factory_interface { typedef T type; };	template < typename KeyT , typename InterfaceT , typename MethodsT > class factory_base;}#include "industry.methods.hpp"#include "industry.factory.detail.base.hpp"#include "industry.factory.exception.hpp"namespace industry {	/* examples:		industry::factory< boost::any , industry::methods< void ( void ) , void ( unsigned ) > >  example;	industry::factory< boost::any , void ( void ) , void ( unsigned ) > example;		*/#define TYPENAME_NIL_Tn          BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( INDUSTRY_METHODS_LIMIT , typename T , nil )#define TYPENAME_Tn              BOOST_PP_ENUM_PARAMS( INDUSTRY_METHODS_LIMIT , typename T )#define Tn                       BOOST_PP_ENUM_PARAMS( INDUSTRY_METHODS_LIMIT , T )#define NIL_instance(z,n,u)      nil#define TRAILING_NILn_MINUS_ONE  BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB( INDUSTRY_METHODS_LIMIT , 1 ) , NIL_instance , ~ )#define IMPLEMENTATION           : public factory_base< KeyT , typename factory_interface< InterfaceT >::type , methods< Tn > > {}	template < typename KeyT , typename InterfaceT , TYPENAME_NIL_Tn > class factory      IMPLEMENTATION;	template < typename KeyT , typename InterfaceT , TYPENAME_Tn >	class factory< KeyT , InterfaceT , methods< Tn >  TRAILING_NILn_MINUS_ONE >  IMPLEMENTATION;#undef TYPENAME_NIL_Tn#undef TYPENAME_Tn#undef Tn#undef NIL_instance#undef TRAILING_NILn_MINUS_ONE#undef IMPLEMENTATION}#endif //ndef IG_INDUSTRY_FACTORY


// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// May 31, 2006 - Created// <= INDUSTRY_FACTORY_ASPECT_FILENAME#ifndef IG_INDUSTRY_FACTORY_INTERFACE_ASPECT_GEN_COMMON#define IG_INDUSTRY_FACTORY_INTERFACE_ASPECT_GEN_COMMON  #include <boost/preprocessor/repetition.hpp>  #include <boost/preprocessor/iteration.hpp>  #include "industry.config.hpp"#endif //ndef IG_INDUSTRY_FACTORY_INTERFACE_ASPECT_GEN_COMMON#ifndef BOOST_PP_IS_ITERATING  #ifndef INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMIT  #define INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMIT INDUSTRY_METHOD_ARGUMENTS_LIMIT  #endif //ndef INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMIT  #define BOOST_PP_ITERATION_LIMITS  (0, INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMIT)  #define BOOST_PP_FILENAME_1        "industry.factory.interface.aspect.gen.hpp"  #include BOOST_PP_ITERATE()#else //BOOST_PP_IS_ITERATING  #define INDUSTRY_FACTORY_INTERFACE_ASPECT_IS_GENERATING  #define N                BOOST_PP_ITERATION()  #if N == 0    #define TRAILING_TYPENAME_AN    #define TYPENAME_AN	#define AN	#define A_ARGN                 void	#define ARGN  #else    #define TRAILING_TYPENAME_AN   BOOST_PP_ENUM_TRAILING_PARAMS(N,typename A)    #define TYPENAME_AN            BOOST_PP_ENUM_PARAMS(N,typename A)	#define AN                     BOOST_PP_ENUM_PARAMS(N,A)    #define A_ARGN                 BOOST_PP_ENUM_BINARY_PARAMS(N,A,arg)    #define ARGN                   BOOST_PP_ENUM_PARAMS(N,arg)  #endif  #include INDUSTRY_FACTORY_INTERFACE_ASPECT_FILENAME  #undef INDUSTRY_FACTORY_INTERFACE_ASPECT_IS_GENERATING  #undef N  #undef TRAILING_TYPENAME_AN  #undef TYPENAME_AN  #undef AN  #undef A_ARGN  #undef ARGN#endif //BOOST_PP_IS_ITERATING


// Copyright (c) 2006 Michael B. Edwin Rickert//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt )//// May 31, 2006 - Created#ifndef INDUSTRY_FACTORY_INTERFACE_ASPECT_IS_GENERATING  #ifndef IG_INDUSTRY_FACTORY_INTERFACE_ASPECTS  #define IG_INDUSTRY_FACTORY_INTERFACE_ASPECTS  #include <boost/any.hpp>  #include <boost/shared_ptr.hpp>  #include <boost/preprocessor/repetition.hpp>  #include <boost/variant.hpp>  #include "industry.factory.hpp"namespace industry {	template < typename ReturnT , typename Method > struct return_coerced_interface_method_impl;	template < typename ReturnT > struct return_coerced_interface_method_impl< ReturnT , void ( void ) > {		typedef ReturnT (type)(void);		typedef ReturnT return_type;	};	#define METHOD_IMPL(z,n,unused)                           	template < typename ReturnT , BOOST_PP_ENUM_PARAMS(n,typename A) >  	struct return_coerced_interface_method_impl               		< ReturnT , void ( BOOST_PP_ENUM_PARAMS(n,A) ) > {    		typedef ReturnT (type)( BOOST_PP_ENUM_PARAMS(n,A) );  		typedef ReturnT return_type;                          	};	BOOST_PP_REPEAT_FROM_TO(1,INDUSTRY_FACTORY_METHOD_ARGUMENTS_LIMIT,METHOD_IMPL,~)	#undef METHOD_IMPL		template < typename ReturnT >	struct return_coerced_interface {		template < typename Method > struct method : return_coerced_interface_method_impl< ReturnT , Method > {};	};	namespace factory_detail {		template < typename T , typename Method > struct boost_any_interface_aspect_impl;		struct boost_any_interface : return_coerced_interface< boost::any > {			template < typename T , typename Method > struct aspect : boost_any_interface_aspect_impl<T,Method> {				using boost_any_interface_aspect_impl<T,Method>::create;			};					};				template < typename B , typename T , typename Method > struct boost_shared_ptr_interface_aspect_impl;		template < typename B > struct boost_shared_ptr_interface : return_coerced_interface< boost::shared_ptr< B > > {			template < typename T , typename Method > struct aspect : boost_shared_ptr_interface_aspect_impl<B,T,Method> {				using boost_shared_ptr_interface_aspect_impl<B,T,Method>::create;			};		};				template < typename B , typename T , typename Method > struct std_auto_ptr_interface_aspect_impl;		template < typename B > struct std_auto_ptr_interface : return_coerced_interface< std::auto_ptr< B > > {			template < typename T , typename Method > struct aspect : std_auto_ptr_interface_aspect_impl<B,T,Method> {				using std_auto_ptr_interface_aspect_impl<B,T,Method>::create;			};		};				#define VARIANT_TYPENAMES   BOOST_PP_ENUM_PARAMS( BOOST_VARIANT_LIMIT_TYPES , typename V )		#define VARIANT_TYPES       BOOST_PP_ENUM_PARAMS( BOOST_VARIANT_LIMIT_TYPES , V )		#define VARIANT_TYPE        boost::variant< VARIANT_TYPES >		template < VARIANT_TYPENAMES , typename T , typename Method > struct boost_variant_interface_aspect_impl;		template < VARIANT_TYPENAMES >		struct boost_variant_interface : return_coerced_interface< VARIANT_TYPE > {			template < typename T , typename Method > struct aspect				: boost_variant_interface_aspect_impl<VARIANT_TYPES,T,Method> {				using boost_variant_interface_aspect_impl<VARIANT_TYPES,T,Method>::create;			};		};		#undef VARIANT_TYPENAMES		#undef VARIANT_TYPES		#undef VARIANT_TYPE				template < typename B , typename T , typename Method > struct raw_ptr_interface_aspect_impl;		template < typename B > struct raw_ptr_interface : return_coerced_interface< B * > {			template < typename T , typename Method > struct aspect : raw_ptr_interface_aspect_impl<B,T,Method> {				using raw_ptr_interface_aspect_impl<B,T,Method>::create;			};		};	}	template <> struct factory_interface< boost::any > {		typedef factory_detail::boost_any_interface type;	};		template < typename B > struct factory_interface< boost::shared_ptr< B > > {		typedef factory_detail::boost_shared_ptr_interface< B > type;	};		template < typename B > struct factory_interface< std::auto_ptr< B > > {		typedef factory_detail::std_auto_ptr_interface< B > type;	};		template < BOOST_PP_ENUM_PARAMS( BOOST_VARIANT_LIMIT_TYPES , typename T ) >	struct factory_interface< boost::variant< BOOST_PP_ENUM_PARAMS( BOOST_VARIANT_LIMIT_TYPES , T ) > > {		typedef factory_detail::boost_variant_interface< BOOST_PP_ENUM_PARAMS( BOOST_VARIANT_LIMIT_TYPES , T ) > type;	};		template < typename B > struct factory_interface< B * > {		typedef factory_detail::raw_ptr_interface< B > type;	};}  #define INDUSTRY_FACTORY_INTERFACE_ASPECT_FILENAME "industry.factory.interface.aspects.hpp"  #include "industry.factory.interface.aspect.gen.hpp"  #undef INDUSTRY_FACTORY_INTERFACE_ASPECT_FILENAME  #endif //ndef IG_INDUSTRY_FACTORY_INTERFACE_ASPECTS#else //INDUSTRY_FACTORY_INTERFACE_ASPECT_IS_GENERATINGnamespace industry {	namespace factory_detail {		template < typename T   TRAILING_TYPENAME_AN >		struct boost_any_interface_aspect_impl< T , boost::any ( AN ) > {			//typedef boost::any (function_type)( AN );			static boost::any create( A_ARGN ) {				return boost::any( T( ARGN ) );			}		};		template < typename B , typename T  TRAILING_TYPENAME_AN >		struct boost_shared_ptr_interface_aspect_impl< B , T , boost::shared_ptr< B > ( AN ) > {			//typedef boost::shared_ptr< B > (function_type)( AN );			static boost::shared_ptr< B > create( A_ARGN ) {				return boost::shared_ptr< B >( new T( ARGN ) );			}		};		template < typename B , typename T  TRAILING_TYPENAME_AN >		struct std_auto_ptr_interface_aspect_impl< B , T , std::auto_ptr< B > ( AN ) > {			static std::auto_ptr< B > create( A_ARGN ) {				return std::auto_ptr< B >( new T( ARGN ) );			}		};				#define VARIANT_TYPENAMES  BOOST_PP_ENUM_PARAMS( BOOST_VARIANT_LIMIT_TYPES , typename V )		#define VARIANT_TYPES      BOOST_PP_ENUM_PARAMS( BOOST_VARIANT_LIMIT_TYPES , V )		#define VARIANT_TYPE      boost::variant< VARIANT_TYPES >		template < VARIANT_TYPENAMES , typename T  TRAILING_TYPENAME_AN >		struct boost_variant_interface_aspect_impl< VARIANT_TYPES , T , VARIANT_TYPE ( AN ) > {			static VARIANT_TYPE create( A_ARGN ) {				return VARIANT_TYPE( T( ARGN ) );			}		};		#undef VARIANT_TYPENAMES		#undef VARIANT_TYPES		#undef VARIANT_TYPE				template < typename B , typename T  TRAILING_TYPENAME_AN >		struct raw_ptr_interface_aspect_impl< B , T , B * ( AN ) > {			static B * create( A_ARGN ) {				return new T( ARGN );			}		};	}}#endif //INDUSTRY_FACTORY_INTERFACE_ASPECT_IS_GENERATING


Note: Many dependant libraries upon which this builds upon omitted, as well as the accompanying unit tests

And now, the equivilant in Ruby:

module Industry    class NewFactoryAspect        def create( type , args )            type.new( *args )        end    end    class Factory        def initialize( key_type , aspect )            @key_type = key_type            @aspect = aspect            @types = {}        end        def type( key , type_mapped )            return nil if @types[ key ]            @types[ key ] = type_mapped        end        def auto_type( type_mapped )            raise "Factory#auto_type : @key_type != Class" unless @key_type == Class            type( type_mapped , type_mapped )        end        def create( key , *args )            @aspect.create( @types[ key ] , args )        end    endend


1 (including dependancies) file instead of 8 (not including dependancies), and that 1 file is shorter than the rest as well.

EDIT: I take that back, industry.factory.exceptions.hpp is smaller (at least if you don't count the copyright/changelog preamble)

Comparing uses:

//C++:struct foo { foo( int ) {} };struct bar { bar( int ) {} };industry::factory< bool , boost::variant< foo , bar > , void ( int ) > simple_factory;simple_factory.type< foo >( true  );simple_factory.type< bar >( false );boost::variant< foo , bar > object = simple_factory.create( false , 42 );assert( object.type() == typeid(bar) );


# Ruby:class Foo; def initialize( arg1 ); end; endclass Bar; def initialize( arg2 ); end; endsimple_factory = Industry::Factory.new( Boolean , Industry::NewFactoryAspect )simple_factory.type( true  , Foo )simple_factory.type( false , Bar )object = simple_factory.create( false , 42 )assert( object.kind_of? Bar )


This is the reason I've come to hate C++.

[Edited by - MaulingMonkey on October 10, 2006 10:59:25 PM]
ToohrVyk
ToohrVyk
C++ is very verbose, it is a very good example of a known computer science conundrum: the compiler knowing less with the programmer writing more.

I find it quite representative of this that the language provides a simple shortcut for a basic operation (incrementing), but no provisions for functional programming support, even though the latter greatly surpasses the former in scope expressivity.

As a whole, C++ is implementation-friendly, but neither compiler-friendly nor user friendly. This kind of philosophy is bound to create friction and unefficiency down the way.


Aardvajk
Aardvajk
Well, I'm a complete C++ idiot and don't know anything else, but I do feel that one of its biggest weaknesses, reflected by a lot of the comments above about header files, is that it has inherited its "modular" system from C.

It does seem a bit ridiculous that the main way to communicate information across different translation units is still performed by the antiquated pre-processor.

But, as has been pointed out many many times on these forums, one of the major reasons for C++'s commercial sucess was its backwards compatibility with C and I think that when judging a language you need to consider not just theoretical computer-science and languague theory issues but also the social and economic reasons that languages survive and flourish.

People bemoan the boiler-plate aspects of C++, in particular with templates, but I am not aware of any feature of C++ that is not as efficient as is possible within the compiliation model it was stuck with.

Obviously there are many ways it could have been improved. I'm thinking, for example, about D when I say that, which has a module system more similar to C# as I understand it. But if these improvements had broken the ease of transition from C to C++, I think it is doubtful it would be the popular languge it is today.
ApochPiQ
ApochPiQ
Pretty much all the big stuff has been covered:

  • The compilation model SUCKS. Seriously, use a .Net language for ten minutes and then tell me you don't revile the very existence of the header/implementation system.

  • It's a minefield. You basically have to memorize the spec to know what a given blurb of code might be doing - if its behavior is rational (i.e. "defined") at all.

  • It's pathetically inexpressive. No first class functions, extremely weak metaprogramming (calling template metaprogramming a viable MP solution is rather like calling a Universal Turing Machine a viable gaming platform, or BrainFuck a viable enterprise business logic platform), no extensibility to the language itself, etc.

  • The standard library is painfully skeletal - it was sufficient 15 years ago when machines were basically glorified terminals, but the world's moved on ever so slightly.

  • Widespread fixation with the use of threads for concurrency. I'm going to leave it at that lest I succumb to the urge to vomit repeatedly and then gouge my eyes out with a spork.


Basically, C++ and the entire standard behind it is myopic, anachronistic, and stubbornly ignorant of modern technology. To be fair, that's due largely to a rather unfortunate requirement backwards-compatibility, coupled with the inherent inertia of a bureaucracy controlling one of the most widespread languages in use. C++ was sort of doomed to its state of undead half-extinction from the outset, by demanding C compatibility, and by being so easily adopted by existing C houses; it attained popularity quickly, but at the sacrifice of agility and longevity. Now it just has too much inertia to die, so it's going to be a rotting zombie mess for many years of the foreseeable future.
Will F
Will F
Quote:
Original post by ApochPiQ
It's a minefield. You basically have to memorize the spec to know what a given blurb of code might be doing - if its behavior is rational (i.e. "defined") at all.


/me points in the direction of Washu's journal

Quiz 1
Quiz 2
Quiz 3
Quiz 4

Washu's comments on the first quiz.

If anyone wants to try the quizzes, Here's a hint, many of the correct answers include the words undefined behavior.
Aardvajk
Aardvajk
Quote:
Original post by ApochPiQ
Basically, C++ and the entire standard behind it is myopic, anachronistic, and stubbornly ignorant of modern technology. To be fair, that's due largely to a rather unfortunate requirement backwards-compatibility, coupled with the inherent inertia of a bureaucracy controlling one of the most widespread languages in use. C++ was sort of doomed to its state of undead half-extinction from the outset, by demanding C compatibility, and by being so easily adopted by existing C houses; it attained popularity quickly, but at the sacrifice of agility and longevity. Now it just has too much inertia to die, so it's going to be a rotting zombie mess for many years of the foreseeable future.


[grin]

If I was Bjarne Stroustrup, I'd want that read out at my funeral.
Nitage
Nitage
The boost libraries are an excellent showcase of what's wrong with C++.

Many of them do simple things - thing that you would take for granted in other languages. However, the implementations of those boost libraries are usually amazingly complex and unwieldy. Although most things are possible in C++, many things are far to difficult to be practical.
Kylotan
Kylotan
I think some replies are a little harsh on C++. It's a great language, for what it is. It's object-oriented C, with a nifty generic algorithms and container library. The emphasis is to give you as much power as possible while never trading away efficiency. Thus, it is probably the best language when you need to have the absolute final say over execution speed, memory usage, or code size.

The problem, is that 'what it is' is too often twisted to fit in categories it wasn't designed for, or perhaps to be more accurate, categories that other languages explicitly were designed for and which fit better. These languages trade away a bit of control in return for doing a lot of the heavy lifting for you. Most of the time, this is exactly what you need. Things like C++'s Boost library are typically just wordy and error-prone versions of things that are built right into another language's syntax - a stop-gap library for people who are finding their C++ app is growing to such an extent that using another language would make life simpler.

And this is what it's about - making development simpler. Everything I do in Python, I can do in C++. But doing it in C++ requires twice the typing, is half as readable, and introduces more than twice the capability for error.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.