From: Road Dog on
This seems to work fine:

template <typename A, typename B, typename C>
class D
{
};

template <typename A, typename C>
class D<A, void, C>
{
};

but this:

template <typename A, typename B, void (A::*MF)(B)>
class D
{
};

template <typename A, void (A::*MF)()>
class D<A, void, MF>
class D
{
};

produces:

test4.cc:17: error: invalid parameter type 'void'
test4.cc:12: error: in declaration 'template<class T, class W, void
(T::* MF)(W)> struct Whatever'
test4.cc:17: error: '<type error>' is not a valid type for a template
constant parameter

This:

class C<A, void, void (T::*MF)()>

is no better.

Is there some way to specialize on 'void' here ?

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Thomas Maeder on
Road Dog <noone(a)nowhere.com> writes:

> template <typename A, typename B, typename C>
> class D
> {
> };
>
> template <typename A, typename C>
> class D<A, void, C>
> {
> };
>
> template <typename A, typename B, void (A::*MF)(B)>
> class D
> {
> };
>
> template <typename A, void (A::*MF)()>
> class D<A, void, MF>
> class D
> {
> };
>
> produces:
>
> test4.cc:17: error: invalid parameter type 'void'
> test4.cc:12: error: in declaration 'template<class T, class W, void
> (T::* MF)(W)> struct Whatever'
> test4.cc:17: error: '<type error>' is not a valid type for a template
> constant parameter

[It's always a bit irritating if people don't post the code that they
have tested. The code you posted contains an obvious typo, and the
parameters on (what the gcc error messages call) line 12 don't match
the code.]

Try this:

template <typename A, typename B>
class D<A, B, void (A::*)(B)>
{
};

template <typename A>
class D<A, void, void (A::*)()>
{
};

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 7 Apr., 18:13, Road Dog <no...(a)nowhere.com> wrote:
> This seems to work fine:
>
> template <typename A, typename B, typename C>
> class D
> {
>
> };
>
> template <typename A, typename C>
> class D<A, void, C>
> {
>
> };
>
> but this:
>
> template <typename A, typename B, void (A::*MF)(B)>
> class D
> {
>
> };
>
> template <typename A, void (A::*MF)()>
> class D<A, void, MF>
> class D
> {
>
> };
>
> produces:
>
> test4.cc:17: error: invalid parameter type 'void'
> test4.cc:12: error: in declaration 'template<class T, class W, void
> (T::* MF)(W)> struct Whatever'
> test4.cc:17: error: '<type error>' is not a valid type for a template
> constant parameter
>
> This:
>
> class C<A, void, void (T::*MF)()>
>
> is no better.
>
> Is there some way to specialize on 'void' here ?

Not exactly with the primary class template, that
you provided above. The point is that any function
type R()(A1) with typenames R and A1 will never
match with something that actually has the pattern
R()() which is essentially the same as R()(void) in
C++, see [dcl.fct]/2:

"[..] The parameter list (void) is equivalent to the
empty parameter list. Except for this special case,
void shall not be a parameter type [..]"

Therefore, without variadic template parameters, it
is impossible to express an empty parameter set given
any type argument, e.g. C++0x would allow you to write
a template like this

template<class R, class ... Types> R f(Types ... args);

*including* the case where args corresponds to the empty
parameter set.

Now being in C++03, what about the following approach,
which has some further advantages, because it can be
specialized for even more cases:

template <typename T, T MF>
class D; // Declared, not defined

template<typename A, void (A::*MF)()>
class D<void(A::*)(), MF>
{
};

template<typename A, typename B, void (A::*MF)(B)>
class D<void(A::*)(B), MF>
{
};

struct W {
void foo();
void bar(double);
};

D<void(W::*)(), &W::foo> wf;
D<void(W::*)(double), &W::bar> wb;

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 8 Apr., 00:26, Thomas Maeder <mae...(a)glue.ch> wrote:
> Try this:
>
> template <typename A, typename B>
> class D<A, B, void (A::*)(B)>
> {
>
> };
>
> template <typename A>
> class D<A, void, void (A::*)()>
> {
>
> };

Hmmh, OK, I throw in the towel: *How* did you define the
primary class template that this works as written??

[You are right, that there is a blatant typo in the OP, but
I don't think that above specialization is correct. For more
details, see my seperate posting]

Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Thomas Maeder on
Daniel Kr�gler <daniel.kruegler(a)googlemail.com> writes:

> On 8 Apr., 00:26, Thomas Maeder <mae...(a)glue.ch> wrote:
>> Try this:
>>
>> template <typename A, typename B>
>> class D<A, B, void (A::*)(B)>
>> {
>>
>> };
>>
>> template <typename A>
>> class D<A, void, void (A::*)()>
>> {
>>
>> };
>
> Hmmh, OK, I throw in the towel: *How* did you define the
> primary class template that this works as written??

template <typename A, typename B, typename C>
class D
{
};


> [You are right, that there is a blatant typo in the OP, but
> I don't think that above specialization is correct. For more
> details, see my seperate posting]

I don't understand your point. Maybe because I don't understand the
OP's intention, and you do. Or maybe vice versa :-)


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]