template< unsigned int array_size = 3 >
class A {
unsigned char array_[ array_size ];
unsigned int array_size_;
public:
A(): array_( new unsigned char[array_size] ), array_size_( array_size ) {};
};
class B {
A<?> a_;
public:
B( int arbitrary, int vars ) {};
};
template class members
Hi. I was wondering if somebody could help me with this bit of code.
I have a templated class A, that takes a non-type parameter for a simple array dimension. And I have a class B that needs to hold a certain class A based on unrelated values. How can I have a templated member when its type is unknown?
I don't want class B parameterized, and I'd rather not have class A inherit from a base class, but these seem to be my only options. If anyone as any insight into this, I'd appreciate it greatly. Thanks.
The declaration for A doesn't make much sense: you have a fixed-size array as a member, attempt to initialize it with a pointer to a dynamically allocated array, and store the size (which can't change) as yet another member.
But if I understand the situation correctly you have a set of types (class template A) and want to use instances of those types polymorphically (in B). That usually means inheritance in C++ (specifically a common base class for A).
Wouldn't you be better off using arrays of dynamic size in A (making it a regular class)? Is it critically important to keep the array size known at compile time?
But if I understand the situation correctly you have a set of types (class template A) and want to use instances of those types polymorphically (in B). That usually means inheritance in C++ (specifically a common base class for A).
Wouldn't you be better off using arrays of dynamic size in A (making it a regular class)? Is it critically important to keep the array size known at compile time?
Quote:Original post by spock
The declaration for A doesn't make much sense: you have a fixed-size array as a member, attempt to initialize it with a pointer to a dynamically allocated array, and store the size (which can't change) as yet another member.
The real constructor looks like this:
A(): array_size_( array_size ) {};
Quote:Wouldn't you be better off using arrays of dynamic size in A (making it a regular class)? Is it critically important to keep the array size known at compile time?
There will only be 4 different instance types of class A. I have a templated function in class B that's parameterized by A class type. This function can work with all instances of class A except for A< 3 >, which I have a specialization for:
template< class AType >void B::UseA( AType pixel );template<>void B::UseA< A< 3 > >( A< 3 > a );
B::UseA is involved in rather tight loops, so I didn't want to check A's size every time I called B::UseA, so instead I parameterized A and B and left the type checking to the compiler.
I would like to typedef A in B (or store an actual A, either one) so that I can create instances of A based on B's members.
It seems like you want compile-time issue (template parameter) to be determined at run-time, which cannot be done. However, there may be ways around. I would however like to get a better understanding of what it is you're actually doing. In particular, how does B's member a_ relate to the A passed to B::UseA? You might be able to do what you want with a variant (i.e. boost::variant):
Enigma
class B{ boost::variant< A< 1 >, A< 2 >, A< 3 >, A< 4 > > a_; public: B(int arbitrary, int vars) : a_((arbitrary < 3) ? ((arbitrary == 1) ? A< 1 >() : A< 2 >()) : ((arbitrary == 3) ? A< 3 >() : A< 4 >())) { } template < unsigned int size > void UseA(A< size > a) { boost::apply_visitor(someVisitor(a), a_); }};
Enigma
Quote:Original post by Enigma
I would however like to get a better understanding of what it is you're actually doing. In particular, how does B's member a_ relate to the A passed to B::UseA?
I'm trying to write a small wrapper for SDL pixels and surfaces. I didn't like SDL's example implementation of PutPixel() checking for a 24-bit pixel depth every time it's called. For 8, 16 and 32 bit depths the addressing and casting are the same, so I parameterized a pixel struct to pass to it, and I parameterized PutPixel() so I could specialize the 24-bit pixel case. I also took the SDL_MapRGBA() call out of there.
However I'm still passing an SDL_Surface * to PutPixel(), and it's still the responsibility of the user (me) to create a correct pixel type for the surface format to pass to PutPixel(). So I was thinking of moving PutPixel() into a surface object, and having a current_value_ pixel type, so I could do this:
Surface surface( 640, 480, 32, SDL_SWSURFACE);...surface.SetPixelColor( 0x80, 0x10, 0x20, 0x00 );surface.PutPixel( 50, 40 );
Although it might be becoming too bloated for my own good. I'll look into boost::variant, thanks for the tip.
EDIT: I could have a regular Surface::PutPixel function which creates a Pixel< surface_->format->BytesPerPixel >, maps color to it using the values stored in Surface::SetPixelColor, and then calls a private parameterized Surface::PutPixel_ function. But if I do that, I might as well have Surface::PutPixel( x, y, r, g, b, a ). I want to be able to put consecutive pixels down without remapping colors every time.
class A { unsigned char* array_; unsigned size_t array_size_;public: A(int array_size = 3): array_( new unsigned char[array_size] ), array_size_( array_size ) {}// And since you'll need them... A(const A& rhs) : array_( new unsigned char(other.array_size_)), array_size_(other.array_size) { std::copy(array_, array_ + array_size_, other.array_); } A& operator=(const A& other) { A rhs(other); std::swap(array_, other.array_); array_size_ = rhs.array_size_; } ~A() { delete[] array_; }// Finally, give read-only access to the size info. size_t size() { return array_size_; }};// On the other hand, you COULD just use std::vector...class B { A a_;public: B( int arbitrary, int vars ) : a_(arbitrary);};template <typename T>void B::doSomethingWith(const T& var) { // etc.}// specialize:template<>void B::doSomethingWith< A >( const A& a ) { if (a.size() == 3) { // do special case stuff here } else { // copy logic from base here. } // That's if I understand you correctly. If all you intend is that // doSomethingWith() works with all sizes of A, then there's no need // for templating at all; just check the size here.}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement