generic programming: (in?)compatibility of CamelCase and snake_case

J

Jeff Schwab

Some people who clearly understand generic programming (probably a good
deal better than I do) seem to prefer CamelCase, even when trying to
interoperate with the C++ standard library. One striking example is
Andrei's book Modern C++ Design. What is the reason for using
CamelCase? Since static identifiers effectively define the interface
supported by each type, how is syntactic compatibility maintained
between CamelCase libraries and the snake_case STL?
 
V

Victor Bazarov

Jeff said:
Some people who clearly understand generic programming (probably a
good deal better than I do) seem to prefer CamelCase, even when
trying to interoperate with the C++ standard library. One striking
example is Andrei's book Modern C++ Design. What is the reason for
using CamelCase? Since static identifiers effectively define the
interface supported by each type, how is syntactic compatibility
maintained between CamelCase libraries and the snake_case STL?

What does a naming convention have to do with syntax? As long as
any identifier is valid and not a reserved one (which a convention
like CamelCase would ensure), what would be the objection to using
it?

V
 
K

Kai-Uwe Bux

Victor said:
What does a naming convention have to do with syntax? As long as
any identifier is valid and not a reserved one (which a convention
like CamelCase would ensure), what would be the objection to using
it?

For instance, in your own container-like classes, would you call the
iterators "iterator" and "const_iterator" or "Iterator"
and "ConstIterator"? The first convention has the advantage that generic
programs using "typename ContainerType::iterator" will work seamlessly with
containers from STL and your own containers.


Best

Kai-Uwe Bux
 
J

Jeff Schwab

Victor said:
What does a naming convention have to do with syntax? As long as
any identifier is valid and not a reserved one (which a convention
like CamelCase would ensure), what would be the objection to using
it?

Consider a naming convention that both method and type names begin with
capital letters. You define a container:

struct MyContainer {
//...

Iterator Begin();
Iterator End();
};

If you have a generic function template designed to work with standard
containers, it will expect the method names to be "begin" and "end", not
"Begin" and "End". To the extent that the actual and expected names
differ, the container and the function become incompatible. The same
holds for traits types, e.g. algorithm implementations may need to know
a container's value_type, rather than its ValueType.

I'm not saying that any particular convention is superior to any other,
but that generic code is only as generic as the naming conventions it
expects. Expecting names to follow a standardized convention is no
different (AFAICS) from expecting iterator types to support prefix
increment and dereference operations, or otherwise associating concepts
with syntax.
 
J

Jim Langston

Jeff said:
Consider a naming convention that both method and type names begin
with capital letters. You define a container:

struct MyContainer {
//...

Iterator Begin();
Iterator End();
};

If you have a generic function template designed to work with standard
containers, it will expect the method names to be "begin" and "end",
not "Begin" and "End". To the extent that the actual and expected
names differ, the container and the function become incompatible. The same
holds for traits types, e.g. algorithm implementations may
need to know a container's value_type, rather than its ValueType.

I'm not saying that any particular convention is superior to any
other, but that generic code is only as generic as the naming
conventions it expects. Expecting names to follow a standardized
convention is no different (AFAICS) from expecting iterator types to
support prefix increment and dereference operations, or otherwise
associating concepts with syntax.

I like CamelCase becuase it's easier to read. I don't like some of the
suggestions such as classes starting with a capital letter, variables not or
vice versa becuase it is to easy to simply get it wrong. Typing an E
instead of an e for example being a hard bug to find.

I also kinda of like the fact that the STL uses all small letters and my own
variables and classes use CamelCase, it's fairly easy on a glance of a
program to determine what is coming from where. But in the long run, it
doesn't matter. Whatever your organization decides upon everyone use it. I
don't think there really is a right way.

The same with some classes having private variables and methods end with _
such as MyVar_ some people like it, some people don't. If you don't like
it, don't use it in your organization. If you do, try to get it used in
your organization. I really don't think there is a consensus amongst C++
programmers which is best nor do I feel there will ever be. Just be
flexible enough to use whatever formatting your orgranization calls for.
 
A

Andrey Tarasevich

Jeff said:
Some people who clearly understand generic programming (probably a good
deal better than I do) seem to prefer CamelCase, even when trying to
interoperate with the C++ standard library. One striking example is
Andrei's book Modern C++ Design. What is the reason for using
CamelCase?

What is the reason of using _any_ case? The "cases" and other conventions you
use is always matters of personal preference (unless your hands are tied by some
coding standard). CamelCase is no worse and no better than any other case,
regardless of what religious followers of other cases might tell you.

Consistency is important, but when the different approaches to naming are
clearly separated (by library boundaries, for example), they don't produce any
problems. Or can even be beneficial.
> Since static identifiers effectively define the interface
supported by each type, how is syntactic compatibility maintained
between CamelCase libraries and the snake_case STL?

I don't see the problem here. What exactly do you mean by "syntactic compatibility"?
 
J

jason.cipriani

Some people who clearly understandgenericprogramming (probably a good
deal better than I do) seem to prefer CamelCase, even when trying to
interoperate with the C++ standard library. One striking example is
Andrei's book Modern C++ Design. What is the reason for using
CamelCase? Since static identifiers effectively define the interface
supported by each type, how is syntactic compatibility maintained
between CamelCase libraries and the snake_case STL?

Reasons for using either would be personal preference; but I think an
accurate way to look at it is: use whatever you want, but be aware
that the STL uses a specific naming convention and therefore places
constraints on what *you* can do if you are designing for STL
compatibility.

The only way syntactic compatibility can be maintained between
CamelCase libraries and snake_case STL is by not strictly adhering to
CamelCase in the libraries -- assuming the STL is the constant factor,
everything else has to be adjusted to maintain compatibility.

My own *personal* preference, as far as capitalization goes, is a sort
of variation on CamelCase with some habits I've developed -- except
when defining types that are supposed to be compatible with the STL,
in which case I stick to STL's naming convention, e.g.
SomeThing::iterator.

Really, the *only* way to maintain that kind of syntactic
compatibility is to, well, use a compatible syntax. Of course:

#define Iterator iterator
<g>

Jason
 
E

Erik Wikström

For instance, in your own container-like classes, would you call the
iterators "iterator" and "const_iterator" or "Iterator"
and "ConstIterator"? The first convention has the advantage that generic
programs using "typename ContainerType::iterator" will work seamlessly with
containers from STL and your own containers.

This is really more a question about making your class conform to a
certain interface than anything else, you have the same problem if your
class derives from some other class that uses some other convention. As
for making you code work with standard library templates I think that
the next version of the standard will have something concept maps which
will solve this issue.
 
J

James Kanze

Consider a naming convention that both method and type names
begin with capital letters. You define a container:
struct MyContainer {
//...
Iterator Begin();
Iterator End();
};

[Nothing to do with your question, but...]

More usual would be:

struct MyContainer
{
// ...
Iterator begin() ;
Iterator end() ;
} ;

One of the goals of a naming convention should be to distinguish
typenames from all other symbols.
If you have a generic function template designed to work with
standard containers,

If you have generic function templates designed to work with
containers, you haven't quite caught philosophy of the standard
library. Generic functions should be designed to work with
iterators. Where the names of the critical functions are *, ++
and ==; it's blatant abuse of operator overloading, but it does
avoid any argument about naming conventions.
it will expect the method names to be "begin" and "end", not
"Begin" and "End". To the extent that the actual and expected
names differ, the container and the function become
incompatible. The same holds for traits types, e.g. algorithm
implementations may need to know a container's value_type,
rather than its ValueType.

Certainly, when you want a name required by an external (to your
code) element, you conform to its requirements. The standard is
just one example; you don't call pthreadCreate, either.

I actually find this one (very small) advantage of camel case:
the reader knows immediately, from the way the name is formed,
whether the intent is to conform with some external convention
or not.
I'm not saying that any particular convention is superior to
any other, but that generic code is only as generic as the
naming conventions it expects. Expecting names to follow a
standardized convention is no different (AFAICS) from
expecting iterator types to support prefix increment and
dereference operations, or otherwise associating concepts with
syntax.

Exactly. The naming convention is part of the interface.
Without the interface requirements, you certainly wouldn't
overload ++ for an iterator, and without the interface
requirements, you might prefer the name ValueType, rather than
value_type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top