Re: Incomplete type in template parameter, complete type as argument
On Apr 16, 11:06 am, "Vidar Hasfjord" <vattilah-gro...@yahoo.co.uk>
wrote:
On Apr 11, 5:01 pm, "James Kanze" <james.ka...@gmail.com> wrote:
Even in C++, the notion of compatible type exists. Whether it applies
with regards to incomplete and complete array types, I'm not sure, and
whether it applies in this case, even less, but the concept is there
(if only for reasons of C compatibility, in certain cases).
In my view the "complete or incomplete type" question is a red herring
in this case. Answering a simpler question; "On which parameters is
the template parameterized?"; seems to give a simple answer that
confirms the compiler error.
[...]
Here is your template again:
template <char const* (&keys) []>
bool accept (char const* key) {
return std::find_if (begin (keys), end (keys), Match (key))
!= end (keys);
}
This template is simply not parameterized on array size.
True. As I said, the problem is that the compiler has the
necessary information, but there's no way to tease it out of it.
[...]
Accept() may not be instantiated with any array whose type is
complete - because that array object has the wrong type to match the
declaration.
In which case, I'd call that a defect in the standard.
Not by my interpretation. There is a mismatch of types like Greg
Herlihy says. The exact type of the array argument passed to the
template cannot be captured because the template is simply not
parameterized on array type (the size in this case).
There are two aspects. As you've pointed out, the template
isn't parameterized on size, only on the "name" of the array.
It seems a little frustrating, but I can see the logic behind
this. On the other hand, I think that not being able to use an
array of known size anywhere an array of unknown size is
required *is* a defect. It doesn't make sense.
The compiler has the information it needs at the point of
instantiation. The problem is how to tease them out of it.
True. It has all the information, but the template as you've declared
it doesn't allow for parameterization on that info (i.e. on the size).
Hence it decays to the parameter type you've specified, an array-of-
unspecified-size type.
Using my declaration above you can implement your table as follows:
Table const tbl [] =
{
{1, &accept <N_ELEMENTS (tab1), tab1>},
{2, &accept <N_ELEMENTS (tab2), tab2>},
};
This is a little more to write but otherwise as you intended.
That is one solution; I'd thought of that. The other solution
would be to modify the code to use a sentinel (so that the
template function doesn't need the length), forward declare the
arrays, with unknown size, instantiate the templates, and only
then define the arrays.
(In practice, the solution was to go back to the classical
solution, using inheritance instead of templates. My playing
around with templates here was only an experiment, to see if it
would make sense.)
If that is too verbose, you can use functors, provided the rest of
your program can be adapted, of course. A functor allows the array
type, the size in this case, to be captured through a templated
constructor:
struct Accept
{
char const* const* keys;
const size_t n;
template <size_t N> Accept (char const* (&k) [N])
: keys (k), n (N) {}
bool operator () (char const* key) {
return std::find_if (keys, keys + n, Match (key))
!= keys + n;
}
};
Table const tbl [] =
{
{1, Accept (tab1)},
{2, Accept (tab2)},
};
I thought of that. I just bothers me that the initialization
ceases to be static (not that it matters, in this case---the
functions using the table are never called from the constructor
of a static object).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
---
[ 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 ]