Re: enum in template memfun in class template - valid C++?
On 4/16/07 6:49 AM, in article
1176719276.514814.262300@n76g2000hsh.googlegroups.com,
"numerical.simulation@web.de" <numerical.simulation@web.de> wrote:
enum Outer { a, b };
template <class T>
class C
{
public:
enum Inner { c, d };
template<Inner I, int dummy> struct Dispatcher;
template<int dummy> struct Dispatcher<c, dummy>
{
static const Outer Show = a;
};
template<int dummy> struct Dispatcher<d, dummy>
{
static const Outer Show = b;
};
public:
template <Inner I> void DoSomething(int j)
{
typedef Dispatcher<I, 1> dispatcher_t;
static const Outer o = dispatcher_t::Show;
}
};
int main()
{
C<double> Test;
Test.DoSomething<C<double>::c>(1);
}
I have 4 questions:
- Is this code valid C++ and why?
No, the above code is not a valid C++ program. Essentially, a mistake in how
each Dispatcher member template partial specializations is declared - means
that neither one is instantiated as intended. So when the compiler looks for
dispatcher_t::Show inside the C<T>::DoSomething() member function template,
it tries to instantiate the (not defined) Dispatcher general template
instead of one of its partial specializations.
- If not, could you explain the reason or point to TRs and wordings
for this?
The reason is quite straightforward - and should be readily apparent to any
C++ programmer after no more than a few hours of intense scrutiny :-).
The problem is that Dispatcher's "Inner" enum nontype parameter is dependent
on the name of the enclosing C template class - which means that Inner's
enumerated values (c and d) are dependent on the enclosing C template class
as well. Yet "c" and "d" as they appear in the Dispatcher partial
specialization does not use a type-dependent syntax - so the compiler
assumes that both are nondependent names of incomplete types.
- How to change the code such that it compiles without altering the
main() body?
To fix the compiler error, specialize the Dispatcher member template with
type-dependent "c" and "d" nontype parameters, like so:
template<int dummy>
struct Dispatcher< C::c, dummy>
{
static const Outer Show = a;
};
template<int dummy>
struct Dispatcher< C::d, dummy>
{
static const Outer Show = b;
};
With this small change the compiler now knows that c and d are
type-dependent names and is therefore able to find them.
(enum solution preferred)
- Do you think this code should be valid C++ for future standards?
No.
Greg
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]