Re: Template functions and const array
ahuggel@gmx.net wrote:
werasm wrote:
Andreas Huggel wrote:
This code works fine with int magic = 42. Is it possible to change the
template so that it works correctly with the commented array instead?
Yes, arrays can be value template arguments, with a few limitations.
Read on.
The question should have been: Is it possible to change the template
to use an array by value instead of a simple integer as the template
parameter?
For the bigger context, which also leads to my second question,
hopefully this explains better:
There are many simple read-only lookup tables in my library, like these
struct Lookup {
int id;
const char* desc;
bool operator==(int key) const { return id == key; }
};
const Lookup fruits[] = {
{ 8, "Apple" },
{ 9, "Orange" }
};
const Lookup nuts[] = {
// similar...
};
Then there are functions to lookup the description for a particular
id, one for each table:
template<typename T, int N>
const T* find(T (&src)[N], int key)
{
const T* rc = std::find(src, src + N, key);
return rc == src + N ? 0 : rc;
}
const char* getFruitDesc(int id)
{
const Lookup* l = find(fruits, id);
return l ? l->desc : "not found";
}
const char* getNutDesc(int id)
{
const Lookup* l = find(nuts, id);
return l ? l->desc : "not found";
}
[snip]
My first question above is to find out if it is possible to replace
the get*Desc functions in the metadata array with pointers
getDesc<fruits> and getDesc<nuts>, which attempts to use the array as
a value template parameter to get different functions at compile time.
template <class T, int N, Lookup (&array)[N]>
const char* getDesc(int id)
{
const T* l = find(array, id);
return l ? l->desc : "not found";
}
//call like this:
char const* val = getDesc<Lookup const, COUNTOF(fruits), fruits>(10);
The array has to be a namespace scope variable or static class member -
it has to have external linkage.
The second question is whether I should be looking at a different
technique to manage read-only reference data in the first place rather
than using all these lookup arrays? E.g., use standard containers (and
put up with initialization code and maybe thread safety issues) or
boost::array (but is there any benefit in this case) or make the code
smarter (and the data dumber) and use some clever pattern instead?
There was an article about this in Overload about a year or so ago. All
manner of slightly-over-the-top approaches were applied to the problem
of accessing read-only arrays of data. What you're doing looks fine,
though if you put your ids in sort order, you can use std::lower_bound
for a potential speedup over std::find (though this is only worth it if
your arrays get over about, say, 20 elements, and you're doing the
lookups a lot - profile).
Read only data of this sort is good in resource constrained
environments, and it does bypass order of initialization and
threadsafety issues. Finally, it is generally at least as concise as the
equivalent container code.
Tom
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]