Is C++ too complex?

Started by
121 comments, last by Vortez 11 years, 5 months ago

Not only is it syntactically legal to write code in the header files: Templated code has to go there.

Template code usually doesn't need to go in header files. Even if you aren't using one of the semi-mythical compilers that support export, there's also explicit instantiation. It's just usually more practical to stick the definitions in headers.
Advertisement

[quote name='Álvaro' timestamp='1355249382' post='5009481']
Not only is it syntactically legal to write code in the header files: Templated code has to go there.

Template code usually doesn't need to go in header files. Even if you aren't using one of the semi-mythical compilers that support export, there's also explicit instantiation. It's just usually more practical to stick the definitions in headers.
[/quote]

Explicit instantiation works in some contexts, but it's a hack to get around the problem that we are pointing out: The problem is still there.
I'm not clear what your point is. I'm only pointing out that your statement that template code has to go into a header (with an italicized has) is not true.

You misinterpreted ChaosEngine.

It's not about the C++ runtime model (on which the pure virtual class acts like an interface indeed), what he criticized was the source code allegedly separation between declaration (header files) and implementation (.cpp files), which IMO violates the DRY principle.
The C# interface-implementation combination seems to violate DRY exactly as much as a pure virtual class and an inheriting concrete class do in C++. Your point was...?
More so, AFAIK the compiler and the preprocessor don't enforce this source code separation, so it's sintatically legal to write code in the header files.
[/quote]Correct. But ChaosEngine said a C# interface is a much cleaner expression of intent than a C++ header file, and my counterpoint was that you can write an equivalent expression in a C++ header file that is not appreciably "less clean". A class which contains nothing but public virtual functions is an interface; there's no way to confuse it for anything else.
My statement that template code has to go into a header is basically true in practice (at least it has to go there in the place where I work, in the standard library implementation and in Boost).

Even if my statement is a bit of a simplification, the point was that not only does the C++ compilation model not enforce the separation of interface and implementation into header and module, but it actually makes it hard to do, even if you are trying to be a good little programmer and follow the convention.

[quote name='Bubsy' timestamp='1355249217' post='5009479']
You misinterpreted ChaosEngine.

It's not about the C++ runtime model (on which the pure virtual class acts like an interface indeed), what he criticized was the source code allegedly separation between declaration (header files) and implementation (.cpp files), which IMO violates the DRY principle.
The C# interface-implementation combination seems to violate DRY exactly as much as a pure virtual class and an inheriting concrete class do in C++. Your point was...?
More so, AFAIK the compiler and the preprocessor don't enforce this source code separation, so it's sintatically legal to write code in the header files.
[/quote]Correct. But ChaosEngine said a C# interface is a much cleaner expression of intent than a C++ header file, and my counterpoint was that you can write an equivalent expression in a C++ header file that is not appreciably "less clean". A class which contains nothing but public virtual functions is an interface; there's no way to confuse it for anything else.
[/quote]

You misinterpreted, it's .h/.cpp source code schema that violates the DRY principle, not the pure virtual base class and its concrete implementation. It's the definition of a single/complete entity into two or more files that is being criticized by me.

My statement that template code has to go into a header is basically true in practice (at least it has to go there in the place where I work, in the standard library implementation and in Boost).

There is no such thing as "the" standard library implementation. There are several standard library implementations that go with different compilers. A C++03 compiler with working export would be able to not put implementations in a header. It would be an extremely bad idea due to the practical issues found with actual export implementations, but again you are confusing practicality with necessity.

I don't disagree with your statement that C++ does not enforce separation of interface and implementation, but your supporting arguments are not one hundred percent correct and you are phrasing them in the form of absolutes. This may seem like nitpicking, but this is, after all, a thread about the complexity of C++.

However, just because there is no system of enforced separation of interface and implementation that does not mean you cannot create separate files for interface and implementation, if you want them, even for template classes. You can place the template interface in one header and the implementation in a file that is included separately. (Some people go a step further and have a third file that only contains forward declarations for the template classes.) The compiler won't see any practical difference from a single included file, but the perceived benefit that other people desire of having one file that has the clean interface without the function implementations is still there.

Correct. But ChaosEngine said a C# interface is a much cleaner expression of intent than a C++ header file, and my counterpoint was that you can write an equivalent expression in a C++ header file that is not appreciably "less clean". A class which contains nothing but public virtual functions is an interface; there's no way to confuse it for anything else.


Until someone decides to add an implementation to for one of those methods. Then it becomes an abstract base class. Hell, it can still be pure virtual and have an implementation.

Ultimately, you're missing the point. The C++ compilation model does not split interface and implementation into two separate files, it splits declaration and definition. They sometimes happen to coincide with interface and implementation, but not quite (see private methods, members etc). This is for the benefit of the compiler not the programmer.

The key point is that this is a legacy of the C compilation model that was built to cope with the hardware restrictions of the time. Most modern languages don't bother with this because it's simply not necessary.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

You could argue that the separation between declaration and implementation is built into the language in C# and java using interfaces, as opposed to C++s frankly demented compilation model.
Yeah the real issue to me isn't the [font=courier new,courier,monospace].h/.cpp[/font] schism, but the actual way in which C++ code is compiled. #include just means copy&paste, whereas in other languages, including a module is a higher level construct. I've often seen CPP files that are 60k lines long, after all the #includes have been resolved... (hence crap like [font=courier new,courier,monospace]WIN32_LEAN_AND_MEAN[/font] being invented). No matter what kind of [font=courier new,courier,monospace].h/.cpp[/font] organisation you use, you can't fix the compilation model (nor the fact that so much of the ABI is implementation defined, which keeps C around for interop).

If you do want to write more C# style code in C++ though, I've worked on a code base that looked like:
//foo.h
#pragma once
class IFoo
{
public:
static IFoo* New();
virtual ~IFoo() {}
virtual void Frobnicate() = 0;
};

//foo.cpp
class Foo : public IFoo
{
int member;
void Frobnicate()
{
member = 42;
printf("hello world");
}
};
IFoo* IFoo::New() { return new Foo; }
p.s. it's not my cup of tea though.


how would you replace the goto in this bit with an exception

for (int bar =0; bar < 100; ++bar)
{
for(int foo = 0; foo < 100; ++foo)
{
if (foo * bar == 100)
{
goto loopBreak;
}
}
}

loopBreak:
printf("%d", 100);


Sorry, been away and a tad late to the party.

There was a great example in Bjarne Stroustrup's book demonstrating throwing an exception out of a deeply nested loop containing the result and then catching it after.
This was however a toy implementation and isn't recommended at all.

I have no problem using a goto in this way (and I do find myself doing similar). In my opinion, this isnt misusing C.

An example of a misuse of a goto (In C++) would involve the classic case of jumping to the end of a function and returning an error code rather than use an exception, whereas in C, this is acceptable.


Try writing your own parser for the language...



Try writing a parser in pure C#, you will run into exactly the same issues. It also happens that there are many more parsers available to C++ than there is C#. And those for C# are usually just bindings to a C++ library anyway.



Almost everyone LOVES Java and hates C, C++,



Everyone loves tablets... doesnt mean it is possible to write good software on one. You would use a proper tool like a PC.

(I should stop defending C++, I usually lose too much reputation points ;). When it comes down to it, it is personal choice. I would be very interested in having an official language choice Poll on these forums though! I would like to know how close C# is to C++ in popularity of (Indie?) games developers.
http://tinyurl.com/shewonyay - Thanks so much for those who voted on my GF's Competition Cosplay Entry for Cosplayzine. She won! I owe you all beers :)

Mutiny - Open-source C++ Unity re-implementation.
Defile of Eden 2 - FreeBSD and OpenBSD binaries of our latest game.

This topic is closed to new replies.

Advertisement