Re: Initializing complex, const, variably-sized structures at compile
time
On Dec 24, 5:34 pm, spacewrench <spacewre...@gmail.com> wrote:
On Dec 24, 4:50 am, Vidar Hasfjord <vattilah-gro...@yahoo.co.uk>
wrote:
[...]
Ooh, that's a great idea! Except I could even do:
struct StringDescriptor {
unsigned len;
const wchar_t *get_data( void ) const { return (wchar_t *)(&len +
1); }
} ;
Yes, my cast to char pointer was unnecessary. I prefer
reinterpret_cast though.
template <size_t N>
struct StringDescriptorBody : public StringDescriptor {
wchar_t data[N];
} ;
Then I don't even need the conversion operator in the template. (Or
perhaps I still do, for some reason that my c++-fu is not yet adequate
to understand.
Unfortunately, that will not work. You cannot use inheritance, because
initializer lists can only be used with POD types. Hence the
conversion operator is needed.
I'll have to play with this a bit. There's still the
problem of getting the wchar_t's into little-endian order on machines
where that's not the default...yuck.)
That sounds like a IO problem that hopefully is orthogonal to the
initialization issue.
See below for corrected and simplified code that should work with
Windows Driver Kit's USB library. Here the template converts to the
Windows' struct which has a placeholder string member of size 1.
namespace usb {
const UCHAR string_descriptor_typetag =
USB_STRING_DESCRIPTOR_TYPE;
template <size_t N>
struct StringDescriptor {
UCHAR bLength; // size in bytes of descriptor
UCHAR bDescriptorType;
wchar_t bString [N];
operator const USB_STRING_DESCRIPTOR& () const {
assert (bLength == sizeof (*this));
assert (bDescriptorType == string_descriptor_typetag);
return reinterpret_cast <const USB_STRING_DESCRIPTOR&>
(*this);
}
};
template <>
struct StringDescriptor <0>; // undefined
} // namespace
// Test utilities
void log (const USB_STRING_DESCRIPTOR& s) {
wcout << "USB_STRING_DESCRIPTOR {"
<< "length = " << s.bLength
<< ", type = " << s.bDescriptorType
<< ", string = " << s.bString
<< "}" << endl;
}
#define ARRAY_SIZE(a) \
(sizeof (a) / sizeof (a [0]))
#define DECL_USB_STR_DSCR(name, str) \
usb::StringDescriptor <ARRAY_SIZE (str)> name = \
{sizeof (name), usb::string_descriptor_typetag, str};
void test_variable_array ()
{
const DECL_USB_STR_DSCR (foo, L"Foo");
log (foo);
const DECL_USB_STR_DSCR (wazoo, L"Wazoo");
log (wazoo);
}
Regards,
Vidar Hasfjord