Topic: Partial Specialization will not work?


Author: comeau@panix.com (Greg Comeau)
Date: Wed, 2 Jul 2003 13:54:29 +0000 (UTC)
Raw View
In article <bdmoq2$uvr$01$1@news.t-online.com>,
Jakob Bieling <netsurf@gmy.net> wrote:
>"johnchx" <johnchx2@yahoo.com> wrote in message
>news:4fb4137d.0306280911.2a47044d@posting.google.com...
>> netsurf@gmy.net ("Jakob Bieling") wrote
>>
>> > I want to partially specialize a template, but I am having trouble
>> > doing so. Here is the template and the specialization I have in mind:
>> >
>> > template <typename T, T* t= 0>
>> > class test
>> > {
>> > };
>> >
>> > template <typename T>
>> > class test <T, 0>
>> > {
>> > };
>> >
>> > The partial specialization should be used whenever 't' is 0. I get the
>> > error "C2754: 'test' : a partial specialization cannot have a dependent
>> > non-type template parameter". I do understand what it means, but why
>> > does the language limit it?
>>
>> There are actually two problems with what you are trying to do.  The
>> first is that a null pointer constant is not a valid template argument
>> for a non-type template parameter of pointer type (14.3.2/5).  So the
>> following should not compile:
>>
>>   template <class T, T* pt>
>>   class someclass {};
>>
>>   someclass<int, 0> first_try;         // error: int != int*
>>
>>   someclass<int, (int*) 0> second_try; // error: 0 not address of
>>                                        // an object with external
>>                                        // linkage
>
>The latter compiles with Comeau. I do not know why it should not. I also
>could not find anything that states that it is not allowed.

There probably is no reason is should not, however, it seems
that both above are corner cases that should be explictly
allowed.   In the meantime look at 14.3.2p5 bullet 2
as well as http://www.comeaucomputing.com/iso/cwg_active.html#354
--
Greg Comeau/ 4.3.0.1: FULL CORE LANGUAGE, INCLUDING TC1
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Thu, 3 Jul 2003 00:40:42 +0000 (UTC)
Raw View
On Tue, 01 Jul 2003 23:44:27 +0000, Jakob Bieling wrote:

> void foo (int) {}
>
> template <typename T, void (*) (T) = 0>
> class test2 {};
>
> template <typename T>
> class test2 <T, 0> {};
>
> test2 <int, (void (*) (T)) 0> mytest2a;    //    should use specialization
> test2 <int, foo> mytest2b;    //    uses 'normal' template
>
>     But I think the explanation johnchx gave (too complicated to implement
> for compiler writers) seems reasonable to me. Guess I will stick to the
> little work-around:
>
> template <typename T>
> void null_func (T) {}
>
> template <typename T, void (*) (T) = null_func <T> >
> class test2 {};
[snip]...

>
>     Well, then I can stick to the template parameter as well, just without
> the specialization.

Yes, you can...... But I guess that's not the functionaliy that you're
looking for. Everytime you call the function, you will have to be sure
that the function is not null_func<T> if you expect some functionaliy, as
in an assumption that after the call to that funtion, something is in some
sort of defined/undefined state. Then again, you could get the address of
null_fun<T> because (I think that all the specializations of a specific
type will be in the same memory location). I not too sure on that though.
Then again, across translation units, you might face problems.

I think that if Daveed Vandavoorde's proposal of metacode is accepted,
then you would probably be able to do what you want, and even more. I
hope, just for the good of mankind that it is accepted. Then
boost::type_traits would be of no use, but a lot of redundancy would have
been reduced.

Regards,
-Dhruv.






---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: richard@ex-parrot.com ("Richard Smith")
Date: Thu, 3 Jul 2003 00:40:53 +0000 (UTC)
Raw View
""Jakob Bieling"" <netsurf@gmy.net> wrote:
>
> "johnchx" <johnchx2@yahoo.com> wrote:
>
> >   template <class T, T* pt>
> >   class someclass {};
> >
> >   someclass<int, 0> first_try;         // error: int != int*
> >
> >   someclass<int, (int*) 0> second_try; // error: 0 not address of
> >                                        // an object with external
> >                                        // linkage
>
>     The latter compiles with Comeau. I do not know why it should not. I
also
> could not find anything that states that it is not allowed.

My understanding is that Comeau is wrong here.  14.3.2/1 is quite clear
about what is allowed as a non-type template argument:

 - an integral constant-expression of integral or enumeration type; or

 - the name of a non-type template-parameter; or

 - the name of an object or function with external linkage, including
   function templates and function template-ids but excluding non-static
   class members, expressed as id-expression; or

 - the address of an object or function with external linkage, including
   function templates and function template-ids but excluding non-static
   class members, expressed as & id-expression where the & is optional
   if the name refers to a function or array; or

 - a pointer to member expressed as described in 5.3.1 .

(int*)0 is none of these, therefore it is not a valid non-type template
argument.

This is covered in Vandevoorde & Josuttis excellent book "C++ Templates --
The Complete Guide" in 8.3.3 where they note:

|  ... there are some constants that are, perhaps surprisingly, not
currently valid:
|
|    * Null pointer constants
|    * Floating-point numbers
|    * String literals

--
Richard Smith


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Thu, 3 Jul 2003 00:41:00 +0000 (UTC)
Raw View
netsurf@gmy.net ("Jakob Bieling") wrote

>     The latter compiles with Comeau.

Yes, I noticed that. And yet....

> I do not know why it should not. I also
> could not find anything that states that it is not allowed.

The trouble, I believe, is that nothing permits it.

14.3.2/1 lists the valid template-arguments to a non-type template
parameter:

  -- an integral constant-expression of integral or enumeration type
  -- the name of another non-type template-parameter
  -- the name of an object or function with external linkage
  -- the address of an object or function with external linkage,
     expressed as "& id-expression" (unless id-expression is the
     name of a function or array)
  -- pointer to member

(paraphrased, not quoting in full)

The only one of these bullets that might possibly cover the null
pointer value is the first:  an integral constant-expression of
integral type.

However, 14.3.2/5 lists the conversions that are performed on
expressions used as non-type template-arguments.  Notably absent (in
the sense that a note points out that it is absent) is the null
pointer conversion.  Quoting:

  Although 0 is a valid template-argument for a non-type
  template-parameter of integral type, it is not a valid
  template-argument for a non-type template-parameter of
  pointer type.

A defect report has been submitted to the standardization committee,
requesting that this limit be removed.  It is in the "open" status:

  http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#354

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Thu, 3 Jul 2003 23:47:42 +0000 (UTC)
Raw View
""Dhruv"" <dhruvbird@gmx.net> wrote in message
news:pan.2003.07.02.06.43.28.31392@gmx.net...
> On Tue, 01 Jul 2003 23:44:27 +0000, Jakob Bieling wrote:
>
> > void foo (int) {}
> >
> > template <typename T, void (*) (T) = 0>
> > class test2 {};
> >
> > template <typename T>
> > class test2 <T, 0> {};
> >
> > test2 <int, (void (*) (T)) 0> mytest2a;    //    should use
specialization
> > test2 <int, foo> mytest2b;    //    uses 'normal' template
> >
> >     But I think the explanation johnchx gave (too complicated to
implement
> > for compiler writers) seems reasonable to me. Guess I will stick to the
> > little work-around:
> >
> > template <typename T>
> > void null_func (T) {}
> >
> > template <typename T, void (*) (T) = null_func <T> >
> > class test2 {};
> [snip]...
>
> >
> >     Well, then I can stick to the template parameter as well, just
without
> > the specialization.
>
> Yes, you can...... But I guess that's not the functionaliy that you're
> looking for. Everytime you call the function, you will have to be sure
> that the function is not null_func<T> if you expect some functionaliy, as
> in an assumption that after the call to that funtion, something is in some
> sort of defined/undefined state. Then again, you could get the address of
> null_fun<T> because (I think that all the specializations of a specific
> type will be in the same memory location). I not too sure on that though.
> Then again, across translation units, you might face problems.


    Oh nono, null_func contains exacly the functionality that is needed (in
my real code it is not just an empty function).
    The reason I wanted this special kind of partial specialization was
this: In a lot of functions the function pointer given through the template
parameter would be used to call that function, to let the user of the class
'insert' specific code into the class. If that was not desired, the user
could pass 0 and the class would use default code. This was done in an
if-statement:

    if (F) (F) else do_default ();

    where F is the name of the function pointer (I forgot to give the
template parameter a name in the above snippets). This worked fine when the
user chose to pass 0 and the if-statement was neatly optimized away. But as
soon as anything but 0 was passed, the if-statement remained (in fully
optimized code!), even though everything was constant and the 'else'
condition could never have been met. A case where the optimizer did not go
all the way. By using the 'null_func approach', I can leave the if-statement
out and put the code of 'do_default' into 'null_func'. So whenever the user
chooses not to 'insert' some specific code, the default code will
automatically be used. Since it is not really a null_func in my case, I
simply called it 'def'.

> I think that if Daveed Vandavoorde's proposal of metacode is accepted,
> then you would probably be able to do what you want, and even more. I
> hope, just for the good of mankind that it is accepted. Then
> boost::type_traits would be of no use, but a lot of redundancy would have
> been reduced.

    I have never heard of 'Daveed Vandavoorde's proposal of metacode', but I
will do a Google search to find out more about it. Thanks a lot for your
help!

regards
--
jb

(replace y with x if you want to reply by e-mail)


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Thu, 3 Jul 2003 23:47:42 +0000 (UTC)
Raw View
"johnchx" <johnchx2@yahoo.com> wrote in message
news:4fb4137d.0307020741.255ff652@posting.google.com...
> netsurf@gmy.net ("Jakob Bieling") wrote
>
> >     The latter compiles with Comeau.
>
> Yes, I noticed that. And yet....
>
> > I do not know why it should not. I also
> > could not find anything that states that it is not allowed.
>
> The trouble, I believe, is that nothing permits it.
>
> 14.3.2/1 lists the valid template-arguments to a non-type template
> parameter:
>
>   -- an integral constant-expression of integral or enumeration type
>   -- the name of another non-type template-parameter
>   -- the name of an object or function with external linkage
>   -- the address of an object or function with external linkage,
>      expressed as "& id-expression" (unless id-expression is the
>      name of a function or array)
>   -- pointer to member
>
> (paraphrased, not quoting in full)
>
> The only one of these bullets that might possibly cover the null
> pointer value is the first:  an integral constant-expression of
> integral type.

    Yes, that is what I thought. Even though I was and am not 100% sure if a
pointer can be called an integral type?

> However, 14.3.2/5 lists the conversions that are performed on
> expressions used as non-type template-arguments.  Notably absent (in
> the sense that a note points out that it is absent) is the null
> pointer conversion.  Quoting:
>
>   Although 0 is a valid template-argument for a non-type
>   template-parameter of integral type, it is not a valid
>   template-argument for a non-type template-parameter of
>   pointer type.

    Oh, that I must have missed. Then it is indeed pretty clear that it is
not allowed. Thanks!

regards
--
jb

(replace y with x if you want to reply by e-mail)


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Fri, 4 Jul 2003 22:08:28 +0000 (UTC)
Raw View
netsurf@gmy.net ("Jakob Bieling") wrote

> "johnchx" <johnchx2@yahoo.com> wrote

> > The only one of these bullets that might possibly cover the null
> > pointer value is the first:  an integral constant-expression of
> > integral type.
>

BTW, I should have said null pointer CONSTANT, not null pointer VALUE,
above.

>     Yes, that is what I thought. Even though I was and am not 100% sure if a
> pointer can be called an integral type?

It can't, but -- strangely enough -- a null pointer constant is not a
pointer:

  A null pointer constant is an integral constant expression
  (5.19) rvalue of integer type that evaluates to zero.  A
  null pointer constant can be converted to a pointer type...

  -- 4.10/1

("Integer type" is defined in 3.9.1/7 as bool, char, wchar_t, and the
signed and unsigned integer types.)

In the following statement

  char* p = 0;

the literal 0 is of type int.  It can be used to initialize a char*
because a standard conversion exists from "an integral constant
expression which evaluates to zero" to a pointer.

It's the fact that this conversion isn't performed on
template-arguments that makes it impossible -- or illegal, anyway ;-)
-- to initialize a non-type template-parameter of pointer type with
the literal 0.

Hope this makes sense!

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Sat, 5 Jul 2003 17:34:37 +0000 (UTC)
Raw View
"johnchx" <johnchx2@yahoo.com> wrote

> netsurf@gmy.net ("Jakob Bieling") wrote

> >     Yes, that is what I thought. Even though I was and am not 100% sure
if a
> > pointer can be called an integral type?

> It can't, but -- strangely enough -- a null pointer constant is not a
> pointer:
>
>   A null pointer constant is an integral constant expression
>   (5.19) rvalue of integer type that evaluates to zero.  A
>   null pointer constant can be converted to a pointer type...
>
>   -- 4.10/1
>
> ("Integer type" is defined in 3.9.1/7 as bool, char, wchar_t, and the
> signed and unsigned integer types.)
>
> In the following statement
>
>   char* p = 0;
>
> the literal 0 is of type int.  It can be used to initialize a char*
> because a standard conversion exists from "an integral constant
> expression which evaluates to zero" to a pointer.
>
> It's the fact that this conversion isn't performed on
> template-arguments that makes it impossible -- or illegal, anyway ;-)
> -- to initialize a non-type template-parameter of pointer type with
> the literal 0.
>
> Hope this makes sense!


    Yes, it does! Thanks a lot for taking the time to find the quotes!

regards
--
jb

(replace y with x if you want to reply by e-mail)


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Tue, 24 Jun 2003 03:46:12 +0000 (UTC)
Raw View
Hi,

    I want to partially specialize a template, but I am having trouble doing
so. Here is the template and the specialization I have in mind:

template <typename T, T* t= 0>
class test
{
};

template <typename T>
class test <T, 0>
{
};

    The partial specialization should be used whenever 't' is 0. I get the
error "C2754: 'test' : a partial specialization cannot have a dependent
non-type template parameter". I do understand what it means, but why does
the language limit it?

Thanks for your help!
--
jb

(replace y with x if you want to reply by e-mail)



---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net (Dhruv)
Date: Tue, 24 Jun 2003 17:18:30 +0000 (UTC)
Raw View
netsurf@gmy.net ("Jakob Bieling") wrote in message news:<bd2m4a$c7i$03$1@news.t-online.com>...
> Hi,
>
>     I want to partially specialize a template, but I am having trouble doing
> so. Here is the template and the specialization I have in mind:
>
> template <typename T, T* t= 0>
> class test
> {
> };
>

> template <typename T>
> class test <T, 0>
> {
> };
>
>     The partial specialization should be used whenever 't' is 0. I get the
> error "C2754: 'test' : a partial specialization cannot have a dependent
> non-type template parameter". I do understand what it means, but why does
> the language limit it?

It means that you either fully specialize a class for a certain
parameter(s) fully. (That's called partial specialization though), or
you don't specialize at all. Partial specialization means have a
different copy of the code generated if all (ALL) the template
parameters correspond to something that the compiler can decipher at
compile time. The partial specilization cannot have types that depend
on a non-specialization, like what 'T' is here. I hope I got that
correct though.

Regards,
-Dhruv.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net (Dhruv)
Date: Wed, 25 Jun 2003 02:02:31 +0000 (UTC)
Raw View
netsurf@gmy.net ("Jakob Bieling") wrote in message news:<bd2m4a$c7i$03$1@news.t-online.com>...



Ok, sorry, the previous post was rubbish, ignore it. It was totally
braindamaged, just like me :-)


This is what you should be doing:

#include <iostream>
using std::cout;
using std::endl;

// template <class T, class U>
// class test {
// public:
//   test () { cout<<"In template1"<<endl; }
// };

// template <class T>
// class test <T, T*> {
// public:
//   test () { cout<<"In spec1"<<endl; }
// };

template <class T, int U>
class test { };

template <class T>
class test <T, 0> { };


int main () {
  test<int, 0> t;

}

If that's the functionality you need. Otherwise, uncomment the
commented region to get a test class that takes as its 2nd argument a
pointer to any type. Here, you cannot specialize for '0', because it
is NOT a type, neither can you pass '0' as a default template
argument. Don;t forget to comment the uncommented part.

And this is definitely not allowed:

template <typename T, T* t= 0>
class test
{
};

template <typename T>
class test <T, 0>
{
};


Regards,
-Dhruv.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: chandra.kumar@oracle.com (Chandra Shekhar Kumar)
Date: Fri, 27 Jun 2003 17:54:43 +0000 (UTC)
Raw View
you can write

template <typename T1, typename T2>
class Test {};

template<typename T1>
class Test<T1, 0> {};


Jakob Bieling wrote:

> Hi,
>
>     I want to partially specialize a template, but I am having trouble doing
> so. Here is the template and the specialization I have in mind:
>
> template <typename T, T* t= 0>
> class test
> {
> };
>
> template <typename T>
> class test <T, 0>
> {
> };
>
>     The partial specialization should be used whenever 't' is 0. I get the
> error "C2754: 'test' : a partial specialization cannot have a dependent
> non-type template parameter". I do understand what it means, but why does
> the language limit it?
>
> Thanks for your help!
> --
> jb
>
> (replace y with x if you want to reply by e-mail)
>
> ---
> [ 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.jamesd.demon.co.uk/csc/faq.html                       ]

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Fri, 27 Jun 2003 17:56:14 +0000 (UTC)
Raw View
"Dhruv" <dhruvbird@gmx.net> wrote in message
news:cf18e89.0306240447.3c3f64f8@posting.google.com...

> And this is definitely not allowed:
>
> template <typename T, T* t= 0>
> class test
> {
> };
>
> template <typename T>
> class test <T, 0>
> {
> };

    This is exactly what I need!

    Why is this not allowed? It soo makes perfect sense to have it working
.. to me at least ;o)  I do pass some kind of T pointer-value as the second
parameter and I might pass 0 for all T. In my case, I do not have T*, but
rather a function pointer type:

    void (*) (T const&, T&);

    And I would like the class to behave differently, if no function pointer
was specified.

regards
--
jb

(replace y with x if you want to reply by e-mail)


PS: Sorry about the "Re:" in the original post subject .. it was left from a
reply from comp.lang.c++, where I was redirected to comp.std.c++ about the
'why'.


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Fri, 27 Jun 2003 20:24:25 +0000 (UTC)
Raw View
"Chandra Shekhar Kumar" <chandra.kumar@oracle.com> wrote in message
news:3EF737B9.885DA592@oracle.com...
> you can write
>
> template <typename T1, typename T2>
> class Test {};
>
> template<typename T1>
> class Test<T1, 0> {};


    No, because 0 is not a type. Other than that, I need the second template
parameter to be a pointer type (function pointer) that depends on the first
template parameter, and not a new typename.

regards
--
jb

(replace y with x if you want to reply by e-mail)


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dhruvbird@gmx.net ("Dhruv")
Date: Sat, 28 Jun 2003 07:24:34 +0000 (UTC)
Raw View
On Fri, 27 Jun 2003 17:56:14 +0000, Jakob Bieling wrote:

> "Dhruv" <dhruvbird@gmx.net> wrote in message
> news:cf18e89.0306240447.3c3f64f8@posting.google.com...
>
>> And this is definitely not allowed:
[snip]...

>     This is exactly what I need!
>
>     Why is this not allowed? It soo makes perfect sense to have it working
> .. to me at least ;o)  I do pass some kind of T pointer-value as the second
> parameter and I might pass 0 for all T. In my case, I do not have T*, but
> rather a function pointer type:
>
>     void (*) (T const&, T&);
>
>     And I would like the class to behave differently, if no function pointer
> was specified.
>

You can not use this approach because a function pointer is type, whereas
0 is a value, not a type. It is a value that that type may hold. So, you
ca specialize on a type, but not on the value that that type holds. If you
want the required behaviour, you will have to implement it as arguments to
a constructor. Something like:

// template <class T, class U>
// class test {
// public:
//   test () { cout<<"In template1"<<endl; }
// };

// template <class T>
// class test <T, T*> {
// public:
//   test () { cout<<"In spec1"<<endl; }
// };

Then say:

template <class T>
test<T>::test (T* ptr_to_t) { if (ptr_to_t) //some behaviour.
else //other behaviour.
}

HTH,
-Dhruv.






---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: johnchx2@yahoo.com (johnchx)
Date: Sat, 28 Jun 2003 17:42:56 +0000 (UTC)
Raw View
netsurf@gmy.net ("Jakob Bieling") wrote

>     I want to partially specialize a template, but I am having trouble doing
> so. Here is the template and the specialization I have in mind:
>
> template <typename T, T* t= 0>
> class test
> {
> };
>
> template <typename T>
> class test <T, 0>
> {
> };
>
>     The partial specialization should be used whenever 't' is 0. I get the
> error "C2754: 'test' : a partial specialization cannot have a dependent
> non-type template parameter". I do understand what it means, but why does
> the language limit it?


There are actually two problems with what you are trying to do.  The
first is that a null pointer constant is not a valid template argument
for a non-type template parameter of pointer type (14.3.2/5).  So the
following should not compile:

  template <class T, T* pt>
  class someclass {};

  someclass<int, 0> first_try;         // error: int != int*

  someclass<int, (int*) 0> second_try; // error: 0 not address of
                                       // an object with external
                                       // linkage

So the specialization you're trying to create could never be
instantiated, even if specializing on a dependent non-type parameter
were permitted.

The second problem, of course, is that you can't specialize on a
dependent non-type parameter.  I'm not absolutely sure of the reason
for this rule, but I suspect that it is meant to spare compiler
writers from having to invent some way to parse and remember literals
(and other compile time constants) of unknown type.  Consider the 0 in
your template specialization -- what is its type?  What is its size?
What is its underlying binary representation?  Is it even a valid
value?  And so on.

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Tue, 1 Jul 2003 23:44:27 +0000 (UTC)
Raw View
""Dhruv"" <dhruvbird@gmx.net> wrote in message
news:pan.2003.06.28.04.47.46.312284@gmx.net...
> On Fri, 27 Jun 2003 17:56:14 +0000, Jakob Bieling wrote:
>
> > "Dhruv" <dhruvbird@gmx.net> wrote in message
> > news:cf18e89.0306240447.3c3f64f8@posting.google.com...
> >
> >> And this is definitely not allowed:
> [snip]...
>
> >     This is exactly what I need!
> >
> >     Why is this not allowed? It soo makes perfect sense to have it
working
> > .. to me at least ;o)  I do pass some kind of T pointer-value as the
second
> > parameter and I might pass 0 for all T. In my case, I do not have T*,
but
> > rather a function pointer type:
> >
> >     void (*) (T const&, T&);
> >
> >     And I would like the class to behave differently, if no function
pointer
> > was specified.
> >
>
> You can not use this approach because a function pointer is type, whereas
> 0 is a value, not a type. It is a value that that type may hold. So, you

    Right, so 0 is a value I could specify as the template parameter. Just
as if I have a template with a parameter of type int:

template <int i>
class test {};

template <>
class test <0> {};

test <0> mytesta;    //    uses specialization
test <1> mytestb;    //    uses 'normal' template

    So I was hoping it would work the same in this case, which it obviously
does not:

void foo (int) {}

template <typename T, void (*) (T) = 0>
class test2 {};

template <typename T>
class test2 <T, 0> {};

test2 <int, (void (*) (T)) 0> mytest2a;    //    should use specialization
test2 <int, foo> mytest2b;    //    uses 'normal' template

    But I think the explanation johnchx gave (too complicated to implement
for compiler writers) seems reasonable to me. Guess I will stick to the
little work-around:

template <typename T>
void null_func (T) {}

template <typename T, void (*) (T) = null_func <T> >
class test2 {};

> ca specialize on a type, but not on the value that that type holds. If you
> want the required behaviour, you will have to implement it as arguments to
> a constructor. Something like:
>
> // template <class T, class U>
> // class test {
> // public:
> //   test () { cout<<"In template1"<<endl; }
> // };
>
> // template <class T>
> // class test <T, T*> {
> // public:
> //   test () { cout<<"In spec1"<<endl; }
> // };
>
> Then say:
>
> template <class T>
> test<T>::test (T* ptr_to_t) { if (ptr_to_t) //some behaviour.
> else //other behaviour.
> }

    Well, then I can stick to the template parameter as well, just without
the specialization.

thanks!
--
jb

(replace y with x if you want to reply by e-mail)


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: netsurf@gmy.net ("Jakob Bieling")
Date: Tue, 1 Jul 2003 23:44:32 +0000 (UTC)
Raw View
"johnchx" <johnchx2@yahoo.com> wrote in message
news:4fb4137d.0306280911.2a47044d@posting.google.com...
> netsurf@gmy.net ("Jakob Bieling") wrote
>
> >     I want to partially specialize a template, but I am having trouble
doing
> > so. Here is the template and the specialization I have in mind:
> >
> > template <typename T, T* t= 0>
> > class test
> > {
> > };
> >
> > template <typename T>
> > class test <T, 0>
> > {
> > };
> >
> >     The partial specialization should be used whenever 't' is 0. I get
the
> > error "C2754: 'test' : a partial specialization cannot have a dependent
> > non-type template parameter". I do understand what it means, but why
does
> > the language limit it?
>
>
> There are actually two problems with what you are trying to do.  The
> first is that a null pointer constant is not a valid template argument
> for a non-type template parameter of pointer type (14.3.2/5).  So the
> following should not compile:
>
>   template <class T, T* pt>
>   class someclass {};
>
>   someclass<int, 0> first_try;         // error: int != int*
>
>   someclass<int, (int*) 0> second_try; // error: 0 not address of
>                                        // an object with external
>                                        // linkage

    The latter compiles with Comeau. I do not know why it should not. I also
could not find anything that states that it is not allowed.


> The second problem, of course, is that you can't specialize on a
> dependent non-type parameter.  I'm not absolutely sure of the reason
> for this rule, but I suspect that it is meant to spare compiler
> writers from having to invent some way to parse and remember literals
> (and other compile time constants) of unknown type.  Consider the 0 in
> your template specialization -- what is its type?  What is its size?
> What is its underlying binary representation?  Is it even a valid
> value?  And so on.

    Makes sense, yes. Thanks for the help!

regards
--
jb

(replace y with x if you want to reply by e-mail)


---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]