 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Guest
|
Posted: Wed Sep 13, 2006 7:49 pm Post subject: request: std::vector with typed indices |
|
|
Hello All,
In my job, I frequently have to implement proprietary comms protocols
that interact with legacy devices or systems.
Typically, I use a std::vector<char> to organize my communication
packets. I use the push_back function to fill a vector with raw bytes
from a communication source, like a serial port, then I access the
elements of the vector with the "[]" or ".at()" functions for further
processing.
The indices that describe the internal organization of a packet are
often specified as "#defines" or "const ints," but if I'm processing
various types of packets, I need different lists of indices. That
always leaves me worried that I (or some future developer) will use the
wrong index for a particular packet type.
I'm wondering if anyone else thinks it would be a good idea to add
another template parameter to the std::vector class, which specifies
the type of argument passed to the "[]" operator or ".at()" function.
This would help ensure that proper indices are used for a certain
vector types.
Below is some code that demonstrates how this style of vector might be
used.
enum EFooPacketIndices
{
fpHeaderIx = 0,
fpTypeIx = 1,
fpBlahIx = 12
}
enum FBarPacketIndices
{
bpHeaderIx = 1,
bpTypeIx = 2,
bpBlahIx = 10
}
int main()
{
vector<char, allocator<char>, EFooPacketIndices> foo_packet(123);
vector<char, allocator<char>, EBarPacketIndices> bar_packet(123);
foo_packet[1] = 'a'; // compiler error
foo_packet[EFooPacketIndices(1)] = 'a'; // no warning
foo_packet[EBarPacketIndices(1)] = 'a'; // compiler error
foo_packet[fpHeaderIx] = 'a'; // OK
foo_packet[bpHeaderIx] = 'a'; // compiler error
}
--
Thanks,
Derek Ross
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Guest
|
Posted: Thu Sep 14, 2006 12:07 am Post subject: Re: request: std::vector with typed indices |
|
|
"Victor Bazarov" wrote:
| Quote: | Wouldn't you rather have your own class template derived from 'vector'
and providing its own operator[] for that? At the first glance it
does not seem like an overly complex task to implement such template;
and as such it probably isn't needed in the standard library, but might
come in handy, so a published implementation of an adapter (that's
what it probably looks like) is useful.
|
Thanks for the comment, that idea seems to work well. (See code below.
Allocators have been ignored.)
Derek.
=====
#include <vector>
#include <iostream>
template<class T, class IndexType = size_t>
class vector_typed_index : public std::vector<T>
{
public:
typedef IndexType index_type;
typedef typename std::vector<T>::size_type size_type;
T& operator[](const index_type& index)
{
return std::vector<T>::operator[](size_type(index));
}
const T& operator[](const index_type& index) const
{
return std::vector<T>::operator[](size_type(index));
}
T& at(const index_type& index)
{
return std::vector<T>::at(size_type(index));
}
const T& at(const index_type& index) const
{
return std::vector<T>::at(size_type(index));
}
explicit vector_typed_index()
:std::vector<T>()
{}
explicit vector_typed_index(size_type n, const T& v = T())
:std::vector<T>(n, v)
{}
vector_typed_index(const vector_typed_index& x)
:std::vector<T>(x)
{}
template<class InIt> vector_typed_index(InIt first, InIt last)
:std::vector<T>(first, last)
{}
};
enum ERxPacketIndices
{
rxHeaderIx = 0, rxSizeIx = 1
};
enum ETxPacketIndices
{
txHeaderIx = 1, txSizeIx = 2
};
int main()
{
vector_typed_index<int, ERxPacketIndices> v1(size_t(5), 123);
vector_typed_index<int, ERxPacketIndices> v1b(size_t(5), 333);
vector_typed_index<int, unsigned char> v2;
vector_typed_index<int, ETxPacketIndices> v3;
vector_typed_index<int> v4;
v1.push_back(11);
v1.push_back(22);
v1.push_back(33);
for(int i = 0 ; i < 1000; i++)v2.push_back(i);
std::cout << v1[rxHeaderIx] << std::endl;
std::cout << v1[ERxPacketIndices(2)] << std::endl;
//std::cout << v1[0] << std::endl; //compiler error.
//std::cout << v1[txHeaderIx] << std::endl; // compiler error.
std::cout << v2[256] << std::endl; // prints 0, because index rolls
over at 256.
std::cout << (v1 == v3) << std::endl;
v4.push_back(234);
std::cout << v4[0] << std::endl;
v1 = v1b;
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Thu Sep 14, 2006 12:52 am Post subject: Re: request: std::vector with typed indices |
|
|
derek (AT) antiquark (DOT) com wrote:
| Quote: | In my job, I frequently have to implement proprietary comms protocols
that interact with legacy devices or systems.
Typically, I use a std::vector<char> to organize my communication
packets. I use the push_back function to fill a vector with raw bytes
from a communication source, like a serial port, then I access the
elements of the vector with the "[]" or ".at()" functions for further
processing.
The indices that describe the internal organization of a packet are
often specified as "#defines" or "const ints," but if I'm processing
various types of packets, I need different lists of indices. That
always leaves me worried that I (or some future developer) will use
the wrong index for a particular packet type.
I'm wondering if anyone else thinks it would be a good idea to add
another template parameter to the std::vector class, which specifies
the type of argument passed to the "[]" operator or ".at()" function.
This would help ensure that proper indices are used for a certain
vector types.
Below is some code that demonstrates how this style of vector might be
used.
enum EFooPacketIndices
{
fpHeaderIx = 0,
fpTypeIx = 1,
fpBlahIx = 12
}
enum FBarPacketIndices
{
bpHeaderIx = 1,
bpTypeIx = 2,
bpBlahIx = 10
}
int main()
{
vector<char, allocator<char>, EFooPacketIndices> foo_packet(123);
vector<char, allocator<char>, EBarPacketIndices> bar_packet(123);
foo_packet[1] = 'a'; // compiler error
foo_packet[EFooPacketIndices(1)] = 'a'; // no warning
foo_packet[EBarPacketIndices(1)] = 'a'; // compiler error
foo_packet[fpHeaderIx] = 'a'; // OK
foo_packet[bpHeaderIx] = 'a'; // compiler error
}
|
Wouldn't you rather have your own class template derived from 'vector'
and providing its own operator[] for that? At the first glance it
does not seem like an overly complex task to implement such template;
and as such it probably isn't needed in the standard library, but might
come in handy, so a published implementation of an adapter (that's
what it probably looks like) is useful.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Guest
|
Posted: Thu Sep 14, 2006 1:10 am Post subject: Re: request: std::vector with typed indices |
|
|
Dave Harris wrote:
| Quote: | If it is to be added I think it should be a wrapper class rather than
another parameter to std::vector, so that it could be used with the TR1
fixed-size array.
It's easy enough to write by hand, so perhaps it isn't really needed in
the standard. Then again, it's good to promote type-safe indexes, so it
could be added for ideological reasons. Have you proposed it to Boost?
|
Along with tr1::array, there could also be wrappers for:
bitset
deque
valarray
maybe basic_string (which doesn't really make sense.)
I'll post a message in the boost forum asking if there's a need for
such a set of wrappers.
Derek.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Thu Sep 14, 2006 2:41 am Post subject: Re: request: std::vector with typed indices |
|
|
derek (AT) antiquark (DOT) com () wrote (abridged):
| Quote: | I'm wondering if anyone else thinks it would be a good idea to add
another template parameter to the std::vector class, which specifies
the type of argument passed to the "[]" operator or ".at()" function.
This would help ensure that proper indices are used for a certain
vector types.
|
I have a similar template class. Mine is based on fixed-sized C-arrays,
though - the use of enum indexes kinda implies the array has a fixed
maximum size, and I don't need push_back to keep track when the array is
being written to.
If it is to be added I think it should be a wrapper class rather than
another parameter to std::vector, so that it could be used with the TR1
fixed-size array.
It's easy enough to write by hand, so perhaps it isn't really needed in
the standard. Then again, it's good to promote type-safe indexes, so it
could be added for ideological reasons. Have you proposed it to Boost?
-- Dave Harris, Nottingham, UK.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
ben.craig@gmail.com Guest
|
Posted: Thu Sep 14, 2006 6:18 pm Post subject: Re: request: std::vector with typed indices |
|
|
| Quote: | template<class T, class IndexType = size_t
class vector_typed_index : public std::vector<T
|
Since you are using public inheritance, there are still operator[]s and
at()s taking size_t parameters. This is probably not what you want
since it circumvents the strong typing you are trying to implement.
What you probably want is private inheritance and lots of "using"
statements, or containment and lots of forwarding functions.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Thu Sep 14, 2006 7:28 pm Post subject: Re: request: std::vector with typed indices |
|
|
derek (AT) antiquark (DOT) com () wrote (abridged):
| Quote: | I'll post a message in the boost forum asking if there's a need for
such a set of wrappers.
|
Ideally there would only be one wrapper, not a set of them. As with
std::stack.
-- Dave Harris, Nottingham, UK.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
ben.craig@gmail.com Guest
|
Posted: Thu Sep 14, 2006 7:42 pm Post subject: Re: request: std::vector with typed indices |
|
|
Pete Becker wrote:
| Quote: | ben.craig (AT) gmail (DOT) com wrote:
template<class T, class IndexType = size_t
class vector_typed_index : public std::vector<T
Since you are using public inheritance, there are still operator[]s and
at()s taking size_t parameters. This is probably not what you want
since it circumvents the strong typing you are trying to implement.
You won't get them accidentally. Try it.
|
Ahh, I had forgotten that the overloaded operator[] would hide the base
class's operator[], so it does indeed prevent unwanted size_t
parameters. However, I stand by my original recommendation.
vector_typed_index no longer models Liskov IS-A or WORKS-LIKE-A (Herb
Sutter's Exceptional C++: Item 22 discusses this issue).
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Thu Sep 14, 2006 10:05 pm Post subject: Re: request: std::vector with typed indices |
|
|
ben.craig (AT) gmail (DOT) com wrote:
| Quote: |
Ahh, I had forgotten that the overloaded operator[] would hide the base
class's operator[], so it does indeed prevent unwanted size_t
parameters. However, I stand by my original recommendation.
vector_typed_index no longer models Liskov IS-A or WORKS-LIKE-A (Herb
Sutter's Exceptional C++: Item 22 discusses this issue).
|
Which only means that you might not be able to use vector_typed where
you can use vector. So don't do that. Template code rarely follows
guidelines developed for inheritance and virtual functions. On the other
hand, if you've written, for example, a template function that takes a
vector and displays its contents in some fancy format, you probably do
what to be able to use it, unchanged, with vector_typed.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Guest
|
Posted: Thu Sep 14, 2006 10:34 pm Post subject: Re: typed_index_wrapper |
|
|
Dave Harris wrote:
| Quote: | Ideally there would only be one wrapper, not a set of them. As with
std::stack.
|
Here's an attempt at a wrapper. I think that to be done properly,
various wrappers would be needed for the various containers, mainly due
to difference in constructors.
The wrapper class takes two parameters: the container type, and the
indexing type.
EG, typed_index_wrapper < vector<int>, EFoo > myvec.
The code below shows how this adapter can be used for std::vector,
std::deque and boost::array. The boost::array causes a compiler error
for aggregate initialization though.
Other containers, such as bitset, valarray, stack and string, are
problematic for reasons mentioned near the bottom.
Derek
=====
#include <iostream>
#include <vector>
#include <deque>
#include <string>
#include <deque>
#include <boost/array.hpp>
template<typename Container, typename IndexType>
class typed_index_wrapper : public Container
{
public:
typedef typename Container::reference reference;
typedef typename Container::const_reference const_reference;
typedef IndexType index_type;
typedef typename Container::size_type size_type;
typedef typename Container::value_type value_type;
typedef Container base_type;
reference operator[](const index_type& index)
{
return Container::operator[](size_type(index));
}
const_reference operator[](const index_type& index) const
{
return Container::operator[](size_type(index));
}
reference at(const index_type& index)
{
return Container::at(size_type(index));
}
const_reference at(const index_type& index) const
{
return Container::at(size_type(index));
}
typed_index_wrapper()
:Container()
{}
typed_index_wrapper(size_t n)
:Container(n)
{}
typed_index_wrapper(size_t n, value_type v)
:Container(n, v)
{}
template<class InIt>
typed_index_wrapper(InIt _begin, InIt _end)
:Container(_begin, _end)
{}
};
enum EFoo { a = 0, b, c };
enum EBar { x = 0, y, z };
#define PRINT(a) std::cout << #a << ": " << (a) << std::endl
int main()
{
std::string s("hello");
// The following containers are demonstrated below:
// std::vector
// boost::array
// std::deque
typed_index_wrapper < std::vector<int>, EFoo > v1(11);
typed_index_wrapper < std::vector<int>, EFoo > v2(22, 33);
typed_index_wrapper < std::vector<int>, EFoo > v3(v1);
typed_index_wrapper < std::vector<int>, EFoo > v4(s.begin(), s.end());
PRINT(v1.size());
PRINT(v2.size());
PRINT(v3.size());
std::cout << std::endl;
PRINT(v1.at(a));
PRINT(v2[a]);
PRINT(v3[a]);
PRINT(v4.at(a));
std::cout << std::endl;
PRINT( v1 == v2 );
PRINT( v1 == v3 );
v1 = v4;
std::cout << std::endl;
typed_index_wrapper< boost::array<int, 25>, EBar > a1;
// a1[0] = 111; // compiler error
// a1[a] = 111; // compiler error
a1[x] = 111;
a1.at(x) = 111;
PRINT(a1.size());
PRINT(a1.at(EBar(0)));
PRINT(a1.at(x));
// Aggregate initialize won't work for boost::array. Message is
// error: `a2' must be initialized by constructor, not by `{...}
//typed_index_wrapper< boost::array<int, 25>, EFoo > a2 =
{444,555,666};
typed_index_wrapper< std::deque<int>, unsigned char> d1(1000, 0);
d1.clear();
for(int i = 0 ; i < 1000 ; i ++ )d1.push_back(i);
PRINT(d1.at(257)); // index will roll over because it's uchar, should
print '1'
// std::bitset will cause problems due to different ctors, and member
functions
// returning a bitset<Bits>.
//
// std::valarray will cause problems due to different ctors, and
indexing functions
// that take a slice or gslice.
//
// std::stack doesn't provide indexed access functions.
//
// std::string has different ctors, and just doesn't seem applicable
to typed indexing.
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Thu Sep 14, 2006 10:51 pm Post subject: Re: request: std::vector with typed indices |
|
|
ben.craig (AT) gmail (DOT) com wrote:
| Quote: | template<class T, class IndexType = size_t
class vector_typed_index : public std::vector<T
Since you are using public inheritance, there are still operator[]s and
at()s taking size_t parameters. This is probably not what you want
since it circumvents the strong typing you are trying to implement.
|
You won't get them accidentally. Try it.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|