1

Due to the need to be able to reference unicode character groups in a header only implementation, I want to declare all the arrays first. Templates allow me to initialize static members in the header, but the code looks messy.

This is just two of the twenty or so groups:

struct CharacterClass 
{
    struct Value
    {
        int l;
        int h;
    };
};

template < int N >
struct Nd : public CharacterClass
{
    static const Value v[];
};

template< int N >
const typename Nd< N >::Value Nd< N >::v[] = { 
    { 0x00030 ,  0x00039 }, { 0x00660 ,  0x00669 }, { 0x006f0 ,  0x006f9 }, { 0x007c0 ,  0x007c9 }, { 0x00966 ,  0x0096f },
    { 0x009e6 ,  0x009ef }, { 0x00a66 ,  0x00a6f }, { 0x00ae6 ,  0x00aef }, { 0x00b66 ,  0x00b6f }, { 0x00be6 ,  0x00bef },
    { 0x00c66 ,  0x00c6f }, { 0x00ce6 ,  0x00cef }, { 0x00d66 ,  0x00d6f }, { 0x00e50 ,  0x00e59 }, { 0x00ed0 ,  0x00ed9 },
    { 0x00f20 ,  0x00f29 }, { 0x01040 ,  0x01049 }, { 0x017e0 ,  0x017e9 }, { 0x01810 ,  0x01819 },     { 0x01946 ,  0x0194f },
    { 0x019d0 ,  0x019d9 }, { 0x01b50 ,  0x01b59 }, { 0x0ff10 ,  0x0ff19 }
};

template < int N >
struct Nl : public CharacterClass
{
    static const Value v[];
};
template< int N >
const typename Nl< N >::Value Nl< N >::v[] = { 
    { 0x016ee ,  0x016f0 },     { 0x02160 ,  0x02182 },  { 0x03007, 0x03007 },  { 0x03021 ,  0x03029},  { 0x03038 ,  0x0303a }
};

Q1: Is it possible to declare the array once in a base class without having to repeat it for each derived type?

Q2: How can I hide the dummy 'int N', so that I can later reference the structs without having to add the template parameter? ie. int x = Nd.v[10].l;

Q3: Is there a better way of doing this?

2 Answers 2

1

I will try to give you an alternative for Q1 you've asked. I don't like to see hard-coded values which are meaningless to the program logics.

Here's a nice trick That I use sometimes:

Create a new file and paste the values in it.

data.dat

{ 0x00030 ,  0x00039 }, { 0x00660 ,  0x00669 }, { 0x006f0 ,  0x006f9 }, { 0x007c0 ,  0x007c9 }, { 0x00966 ,  0x0096f },
{ 0x009e6 ,  0x009ef }, { 0x00a66 ,  0x00a6f }, { 0x00ae6 ,  0x00aef }, { 0x00b66 ,  0x00b6f }, { 0x00be6 ,  0x00bef },
{ 0x00c66 ,  0x00c6f }, { 0x00ce6 ,  0x00cef }, { 0x00d66 ,  0x00d6f }, { 0x00e50 ,  0x00e59 }, { 0x00ed0 ,  0x00ed9 },
{ 0x00f20 ,  0x00f29 }, { 0x01040 ,  0x01049 }, { 0x017e0 ,  0x017e9 }, { 0x01810 ,  0x01819 },     { 0x01946 ,  0x0194f },
{ 0x019d0 ,  0x019d9 }, { 0x01b50 ,  0x01b59 }, { 0x0ff10 ,  0x0ff19 }

now, when you want to repeat it, do the following:

const typename Nd< N >::Value Nd< N >::v[] = { 
#include "data.dat"
};

This way, the preprocessor will paste all this values for you, so you don't need to repeat them all the time.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 for a neat trick. It'll definitely come in handy in the future. But this code needs to be a single header file.
@Waldermort: It is a single header file; data.dat is not a header file.
who said it needs to be a header file?
0

Answering my own questions. I placed the whole combined array in a base class, then derived from that with derived types initializing themselves to an index within the array.

struct CharacterClass 
{
    struct Value
    {
        int l;
        int h;
    };
};

template < int X >
struct Base : public CharacterClass
{
    static const Value v[];
};
template< int X >
const typename Base< X >::Value Base< X >::v[] = { 
    // Nd values length 23 index 0
    { 0x00030 ,  0x00039 }, { 0x00660 ,  0x00669 }, { 0x006f0 ,  0x006f9 }, { 0x007c0 ,  0x007c9 }, { 0x00966 ,  0x0096f },
    { 0x009e6 ,  0x009ef }, { 0x00a66 ,  0x00a6f }, { 0x00ae6 ,  0x00aef }, { 0x00b66 ,  0x00b6f }, { 0x00be6 ,  0x00bef },
    { 0x00c66 ,  0x00c6f }, { 0x00ce6 ,  0x00cef }, { 0x00d66 ,  0x00d6f }, { 0x00e50 ,  0x00e59 }, { 0x00ed0 ,  0x00ed9 },
    { 0x00f20 ,  0x00f29 }, { 0x01040 ,  0x01049 }, { 0x017e0 ,  0x017e9 }, { 0x01810 ,  0x01819 },     { 0x01946 ,  0x0194f },
    { 0x019d0 ,  0x019d9 }, { 0x01b50 ,  0x01b59 }, { 0x0ff10 ,  0x0ff19 },

    // Nl values length 5 index 23
    { 0x016ee ,  0x016f0 }, { 0x02160 ,  0x02182 },  { 0x03007, 0x03007 },  { 0x03021 ,  0x03029},  { 0x03038 ,  0x0303a }
};

template < int _index, int _length >
struct BaseIndex : public Base< 0 >
{
    static const Value * v;
    static const int length;
};
template < int _index, int _length >
const typename BaseIndex< _index, _length >::Value * BaseIndex< _index, _length >::v = &Base::v[ _index ];
template < int _index, int _length >
const int BaseIndex< _index, _length >::length = _length;

struct Nd : public BaseIndex< 0, 23 >
{
};
struct Nl : public BaseIndex< 23, 5 >
{
};

I think just a typedef in the namespace can replace those struct's Nd and Nl.

If there's a better way, I'm still open to suggestions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.