[Newbie] Simple memory class

B

Barzo

Hi,

I tring to define an interface to a simple memory object and I thought
to the following one:

template <class T>
class CMemory
{
public:
//Properties
bool IsEmpty();
bool Initialized();
long ItemsWritten();
long Size();

//Methods

/** Allocate space to contain items of type T */
long Allocate(long num_of_items);

long Read(T* pData, long items);

template <class Iterator>
long Read(Iterator first, Iterator last);

long Write(T* pData, long items);

template <class Iterator>
long Write(Iterator first, Iterator last);

long Release();

private:
vector<T> _buffer;
};

First of all, this could be works?
Is there another way to define read/write through iterators?

Thanks in advance.
Daniele.
 
P

Pascal J. Bourguignon

Barzo said:
Hi,

I tring to define an interface to a simple memory object and I thought
to the following one:

template <class T>
class CMemory
{
public:
//Properties
bool IsEmpty();
bool Initialized();
long ItemsWritten();
long Size();

//Methods

/** Allocate space to contain items of type T */
long Allocate(long num_of_items);

long Read(T* pData, long items);

template <class Iterator>
long Read(Iterator first, Iterator last);

long Write(T* pData, long items);

template <class Iterator>
long Write(Iterator first, Iterator last);

long Release();

private:
vector<T> _buffer;
};

First of all, this could be works?
Is there another way to define read/write through iterators?


0- I prefer the following case conventions:

- global variables, type and class name in CamelCase (with an
initial capital, without a specific prefix).

- local variables, parameters, method names in camelCase (with an
initial lowcase).

- I rather not use underlines in my identifers.



1- Names starting with one or two underlines are reserved to the
system. Do not name it _buffer.

It is unfortunate that you cannot give the same name to a
method and to a field, but since I don't like prefixing the
field name by a letter (mBuffer), and I don't like readers to
be prefixed by get (getBuffer()), nowdays I tend to name fields
suffixed by an underline (which is ok for user identifiers).

vector<T>& buffer();
void setBuffer(const vector<T>& newData);
vector<T>& buffer_;


2- Could this code work?

How could we know? There's no specification. We only know that
we have a "memory" object. What does that mean?



3- Is there another way to define read/write through iterators?

Why would we define iterators to a memory chip? RAM or ROM work
usually by direct access:

Byte readByte(Address address);
void writeByte(Address address,Byte byte);


Perhaps if you could give us a specification where defining
iterators would be meaningful it would be worthwhile to answer
this question more precisely.

In the meantime, it's always possible to define whatever you may
imagine, in software systems. Your imagination is the only limit
(within time and space).
 
B

Barzo

1- Names starting with one or two underlines are reserved to the
system. Do not name it _buffer.

Thanks for the suggestions!
 
2- Could this code work?

     How could we know?  There's no specification.  We only know that
     we have a "memory" object.  What does that mean?

I'm sorry I leave behind some info...
With "Could this code work?" I mean sintactically (I'm quite new to
templates).

I'm writing an audio library and I have to define a memory class that
simply read/write data.

So I thought:
- If a class user has a pointer to some memory (eg. short* pData) and
wants to use the class I need to create read/write methods simply
like:

long Read(T* pData, long items_to_read);

- If a class user has a container or whatever? What kind of methods I
have to create?


Daniele.
 
J

Juha Nieminen

Pascal said:
It is unfortunate that you cannot give the same name to a
method and to a field, but since I don't like prefixing the
field name by a letter (mBuffer)

I had the same prejudice for years, but after giving it a try in
actual code, I actually got infatuated with the custom. I truely find
that it helps readability when I can see from the variable name whether
it's a local variable, a member variable or a variable local to the
compilation unit.

For example, consider a function like this (the code itself is not
important itself, but the naming of the variables is):

void MyClass::foo(int parameter)
{
for(int i = 0; i < parameter; ++i)
{
if(valueArray == someValue)
doSomethingWith(valueArray);
}
}

So where is "valueArray" and "someValue" defined? It's impossible to
know. They could be members of MyClass, or they could be in a nameless
namespace in this compilation unit. In fact, if the function was much
longer and this for-loop was somewhere at the end, the variables could
even be local to the MyClass::foo() function, defined somewhere in the
beginning. In order to know where they are defined you need to look
around. (Some graphical editors help finding the definition point, but
that's only if you have one.)

Now contrast it with this:

void MyClass::foo(int parameter)
{
for(int i = 0; i < parameter; ++i)
{
if(gValueArray == mSomeValue)
doSomethingWith(gValueArray);
}
}

I use a naming convention such that member variables start with an 'm'
and variables global to the compilation unit start with a 'g'. Now it's
immediately obvious that "gValueArray" is in a nameless namespace in
this compilation unit, while "mSomeValue" is a member variable of MyClass.

I can honestly say that since I got accustomed to this quite simple
naming convention, I can read my own code much more easily (especially
months after writing it).

(I also use the naming convention of starting constant names with "k".
And by "constant" I mean things which can be used in places where a
compile-time constant is expected. A "const std::vector<int>" would
still have an "m" or "g" (unless it's local to the function, of course),
because it's not a compile-time constant.)
 
P

Pascal J. Bourguignon

Juha Nieminen said:
Pascal said:
It is unfortunate that you cannot give the same name to a
method and to a field, but since I don't like prefixing the
field name by a letter (mBuffer)

I had the same prejudice for years, but after giving it a try in
actual code, I actually got infatuated with the custom. I truely find
that it helps readability when I can see from the variable name whether
it's a local variable, a member variable or a variable local to the
compilation unit.

For example, consider a function like this (the code itself is not
important itself, but the naming of the variables is):

void MyClass::foo(int parameter)
{
for(int i = 0; i < parameter; ++i)
{
if(valueArray == someValue)
doSomethingWith(valueArray);
}
}

So where is "valueArray" and "someValue" defined? It's impossible to
know. They could be members of MyClass, or they could be in a nameless
namespace in this compilation unit.


Since I distinguish GlobalVariables from localVariables and
memberVariables, it's easy to know that SomeValue would have to be a
global variable in some namespace, while someValue must be either a
local variable (which is seen clearly from it's declaration a few
lines above) or a member variable. Some use the convention of always
prefix this-> for members (variables or functions), but I dont' find
it necessary.

In fact, if the function was much
longer and this for-loop was somewhere at the end, the variables could
even be local to the MyClass::foo() function, defined somewhere in the
beginning.

Or in the middle. But it doesn't matter since functions must not be
long ;-)


I can honestly say that since I got accustomed to this quite simple
naming convention, I can read my own code much more easily (especially
months after writing it).

Indeed, it's mostly a question of getting accustomed to _some_
convention. I just gave my preferences. It's not even the convention
I have to use everyday at work...
 
P

Pascal J. Bourguignon

Barzo said:
I'm sorry I leave behind some info...
With "Could this code work?" I mean sintactically (I'm quite new to
templates).

Syntactically, the best placed to answer is your compiler. If you can
compile that file, then syntactically it can work.

I'm writing an audio library and I have to define a memory class that
simply read/write data.

And how would anything dealing with _audio_ need a memory? Computers
need memory. Intelligent processes (whether natural or artificial)
need memory. Water has memory. But audio stuff needs sounds,
samples, time, sequences, measures, notes, delays, durations, etc. Is
there any memory chip in a violin?

So I thought:
- If a class user has a pointer to some memory (eg. short* pData) and
wants to use the class I need to create read/write methods simply
like:

long Read(T* pData, long items_to_read);

- If a class user has a container or whatever? What kind of methods I
have to create?

The methods to attach to a class don't depend on what the class _has_.
They must depend on what the class _is_.

For example, if you have a class Sequence, since it represents a
sequence of notes positionned in time, you could have methods such as:

class Sequence{
public:
virtual void play(AudioOutput& out,Time& position);
virtual void pause();
virtual void resume(Time& position);
virtual void resume(Duration& offset);
virtual void stop();

virtual std::vector<Note>& getNotes() const;
virtual std::vector<Note>& getNotes(Time& start,Time& end) const;
virtual void addNote(Note& note,Time& position);
virtual void removeNote(Note& note,Time& position);

virtual void transpose(Interval& interval);
virtual void setVolume(Volume& volume);
virtual Volume& getVolume();
// ...
};
 
J

Juha Nieminen

Pascal said:
Since I distinguish GlobalVariables from localVariables

You have a naming clash between global variables and type names.

(Argh, I hate using the name "global variables", because I never use
truely global variables, only variables global to the current
compilation unit. However, I don't know the proper term for those...)
 
J

James Kanze

0- I prefer the following case conventions:
- global variables, type and class name in CamelCase (with an
initial capital, without a specific prefix).
- local variables, parameters, method names in camelCase (with an
initial lowcase).
- I rather not use underlines in my identifers.

That's very much a personal preference. Just define a
convention, and stick with it. About the only objective rules
are:

-- Distinguish between preprocessor symbols and the others.
This is in some ways a absolute rule; on the other hand,
most programs shouldn't define any preprocessor symbols
anyway, except include guards (which should be inserted by
the editor, and should have a format which can't be mistaken
for anything else), so it really doesn't matter. The
"standard" convention, however, is that preprocessor symbols
are all caps. (I don't always follow it myself. But except
for include guards, all of my preprocessor symbols do have a
standard prefix which is all caps, and with very few
exceptions, all have very limited scope---I'll define a
macro for some boilerplate text, invoke it a couple of
times, and then immediately #undef it.)

-- Distinguish between type names and others. C++ parses
differently depending on whether a symbol names a type or
something else. The most frequent convention here is to
start a type name with a capital, anything else with a small
letter.

A lot of coding conventions don't respect this, so it
probably isn't an absolute rule, although I've found it
quite useful. Also, it doesn't address templates---whether
a name designates a template or not also affects parsing,
but all of the conventions I know treat the names of class
templates like type names, and the names of function
templates like function names.

-- Mark the separation of individual words in a symbol. There
are two wide spread conventions here: use an underline
(which looks sort of like a space), or start each new word
with a capital. E.g. "newValue" or "new_value" (but not
"newvalue". Which convention you choose isn't too
important, as long as you choose one, and stick to it.
1- Names starting with one or two underlines are reserved to the
system. Do not name it _buffer.
It is unfortunate that you cannot give the same name to a
method and to a field, but since I don't like prefixing the
field name by a letter (mBuffer), and I don't like readers to
be prefixed by get (getBuffer()), nowdays I tend to name fields
suffixed by an underline (which is ok for user identifiers).
vector<T>& buffer();
void setBuffer(const vector<T>& newData);
vector<T>& buffer_;

Leading and trailing underlines aren't very visible.

In principle, a name like "buffer" (and unqualified noun)
should be a type, not a variable or a function. The variable
would be myBuffer, or someParticularBuffer, and the function
name would contain a verb. And of course, if you follow this
rule strictly, you don't need anything else to distinguish
between typename and others. In practice, however, it doesn't
always work out that well. And some functions are just
"accessors"; conceptually, the function is simply the
presentation at the interface level of a member data element.
In such cases, get... and set.. do seem superfluous to me. So
some sort of convention does seem useful: my current practice is
to prefix member variables with "my" (e.g. myBuffer), and static
member variables with "our" (e.g. ourBuffer); this looks like
the original rule in which variable names should be qualified
nouns.
 
J

James Kanze

Since I distinguish GlobalVariables from localVariables and
memberVariables,

Isn't the correct solution here not to use global variables,
except for things which by there nature have to be global. And
in that case, the name of the thing should identify it enough
that the reader knows that it has to be global.

In practice, I've never found any problem in knowing where to
look for a variable. I use a naming convention for member
variables simply in order to be able to use the "raw" name for
accessor functions.

Distinguishing between the name of a type and the name of a
variable or a function seems far more important to me, since
whether something is the name of type or not determines how you
parse a statement.

[...]
Indeed, it's mostly a question of getting accustomed to _some_
convention. I just gave my preferences. It's not even the
convention I have to use everyday at work...

But you didn't present it like that:). (At least, I got the
impression that you were presenting more or less absolute
rules.)
 
P

Pascal J. Bourguignon

Juha Nieminen said:
You have a naming clash between global variables and type names.

(Argh, I hate using the name "global variables", because I never use
truely global variables, only variables global to the current
compilation unit. However, I don't know the proper term for those...)

Indeed, there are so few global variables in a OO program, that the
probability of a clash is close to 0.
 
P

Pascal J. Bourguignon

James Kanze said:
That's very much a personal preference. Just define a
convention, and stick with it. About the only objective rules
are:

-- Distinguish between preprocessor symbols and the others.
This is in some ways a absolute rule; on the other hand,
most programs shouldn't define any preprocessor symbols
anyway, except include guards (which should be inserted by
the editor, and should have a format which can't be mistaken
for anything else), so it really doesn't matter. The
"standard" convention, however, is that preprocessor symbols
are all caps. (I don't always follow it myself. But except
for include guards, all of my preprocessor symbols do have a
standard prefix which is all caps, and with very few
exceptions, all have very limited scope---I'll define a
macro for some boilerplate text, invoke it a couple of
times, and then immediately #undef it.)

Indeed. Moreover, I noticed recently that you can avoid problems in
macro expansions if you put in all upcase also the macro
parameters. Write:

#define MY_MACRO(ARG1,ARG2) ... ARG1 ... ARG2 ...

instead of:

#define MY_MACRO(arg1,arg2) ... arg1 ... arg2 ...
Leading and trailing underlines aren't very visible.

In the case of member variables, I think that this is not important,
since I will normally use the accessor everywhere (they'll be declared
virtual too, to let subclasses modify the implementation of buffer_).

In principle, a name like "buffer" (and unqualified noun)
should be a type, not a variable or a function. The variable
would be myBuffer, or someParticularBuffer, and the function
name would contain a verb. And of course, if you follow this
rule strictly, you don't need anything else to distinguish
between typename and others. In practice, however, it doesn't
always work out that well. And some functions are just
"accessors"; conceptually, the function is simply the
presentation at the interface level of a member data element.
In such cases, get... and set.. do seem superfluous to me. So
some sort of convention does seem useful: my current practice is
to prefix member variables with "my" (e.g. myBuffer), and static
member variables with "our" (e.g. ourBuffer); this looks like
the original rule in which variable names should be qualified
nouns.

That's cute.
 
P

Pascal J. Bourguignon

James Kanze said:
Since I distinguish GlobalVariables from localVariables and
memberVariables,

Isn't the correct solution here not to use global variables,
except for things which by there nature have to be global. And
in that case, the name of the thing should identify it enough
that the reader knows that it has to be global.

In practice, I've never found any problem in knowing where to
look for a variable. I use a naming convention for member
variables simply in order to be able to use the "raw" name for
accessor functions.

Distinguishing between the name of a type and the name of a
variable or a function seems far more important to me, since
whether something is the name of type or not determines how you
parse a statement.

[...]
Indeed, it's mostly a question of getting accustomed to _some_
convention. I just gave my preferences. It's not even the
convention I have to use everyday at work...

But you didn't present it like that:). (At least, I got the
impression that you were presenting more or less absolute
rules.)

Yes I did:
^ ^^^^^^
 

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

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top