Topic: Q: String literals as template arguments: NOT ?


Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Mon, 18 Apr 1994 10:08:19 GMT
Raw View
In article <Co46qB.59L@eunet.ch> didier@pax.eunet.ch (Didier Frick) writes:
>Is anybody out there able to explain why the following :
>
>template <class c, int v> class TplInt
>{
>}
>
>TplInt<char,10> i;
>
>is valid, while:
>
>template <class c, const char const *n> class TplTxt
>{
>}
>
>TplTxt<char,"Forget it"> t; // Error
>
>gives 'Template argument must be a constant expression' when the template
>is instantiated with Borland C++ 4.0 ?
>
>Isn't a literal string a constant expression ? (From what I could understand
>from the compiler's error messages, it seems to have type char *. In the
>general case, you could modify the literal, so it seems reasonable. However,
>to be still more general, I think it could be advisable to provide a way
>of declaring constant string literals, or to say once and for all that
>they cannot be modified and so will always be const.)
>
>Or maybe a a string literal isn't an expression ?

It's considered an expression, but it isn't considered constant... at least
not in C++.

(At this point you may be thinking to yourself that C wasn't so bad after
all.)

--

-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -




Author: lincmad@netcom.com (Linc Madison)
Date: Wed, 20 Apr 1994 08:28:38 GMT
Raw View
Jamshid Afshar (jamshid@castro.uucp) wrote:
: In article <lincmadCo6t6p.1M1@netcom.com>,
: Linc Madison <lincmad@netcom.com> wrote:
: >Didier Frick (didier@pax.eunet.ch) wrote:
: >: template <class c, const char const *n> class TplTxt { }
:                                  ^^^^^-error, maybe you meant to put it
:                                  after the *, but there's no real reason to

: >: TplTxt<char,"Forget it"> t; // Error
: >
: >: gives 'Template argument must be a constant expression' when the template
: >: is instantiated with Borland C++ 4.0 ?
: >
: >The string literal "Forget it" is of type char[] (ARM 2.5.4).  ARM 14.2
: >requires that any nontype template arguments must be constant-expressions,
: >which an object of type char[] is not, even though it meets the "exact
: >match with trivial conversions" requirement of ARM 13.2 from char[] to
: >const char const *.

: I'm not sure what you mean by "even though it meets the exact match
: requirement", but in addition to constant-expressions ARM 14.2 allows
: nontype template arguments to be addresses of objects or functions
: but the object or function must have *external* linkage.  That's why
: string literals are not allowed.

What I meant is that it meets one of the requirements (exact match) but
not the other (const-expr, address of obj/func with external linkage, or
of static class members).

However, as you pointed out, my suggestion of casting the string literal
to a constant pointer still doesn't suffice to make it meet the other
requirement.

As to the point about the syntax of const char * const n, I got confused
because the original poster had it backwards, as did the first C++ book
I used (Anderson & Heinze, one I do *NOT* recommend!).

: Practical problems would be whether Foo<"Hello"> is required to be the
: same type as a Foo<"Hello"> used elsewhere in the file or in another
: file.  Remember C++ doesn't require the address of identical string
: literals to be the same even if they're used in the same module.

True.  Nor, for that matter, are distinct literals required to have
different addresses.  (They generally do, but the standard doesn't
require it; cf. ARM 2.5.4)  Of course, I suppose this could only happen
if one of the literals had an imbedded \0; e.g., "abc\0efg" and "abc",
but it still brings forth the point that storage of literals is
implementation-dependent.

:  template <class c, const char *n> class TplTxt { };
:  char a[] = "Acceptable";
:  TplTxt<char,a> t;

-- Linc Madison   *   Oakland, California   *   LincMad@Netcom.com




Author: lincmad@netcom.com (Linc Madison)
Date: Wed, 13 Apr 1994 07:37:37 GMT
Raw View
Didier Frick (didier@pax.eunet.ch) wrote:
: Is anybody out there able to explain why the following :

: template <class c, int v> class TplInt { }
: TplInt<char,10> i;

: is valid, while:

The integer constant '10' is of type int.  It matches the template
exactly.

: template <class c, const char const *n> class TplTxt { }
: TplTxt<char,"Forget it"> t; // Error

: gives 'Template argument must be a constant expression' when the template
: is instantiated with Borland C++ 4.0 ?

The string literal "Forget it" is of type char[] (ARM 2.5.4).  ARM 14.2
requires that any nontype template arguments must be constant-expressions,
which an object of type char[] is not, even though it meets the "exact
match with trivial conversions" requirement of ARM 13.2 from char[] to
const char const *.

: Isn't a literal string a constant expression ? (From what I could understand
: from the compiler's error messages, it seems to have type char *. In the
: general case, you could modify the literal, so it seems reasonable. However,
: to be still more general, I think it could be advisable to provide a way
: of declaring constant string literals, or to say once and for all that
: they cannot be modified and so will always be const.)

There is such a mechanism to declare a constant string literal:
const char const * foo = "Foo string";

Alternately, in your example, you can cast your argument:
TplTxt<char, (const char const *) "Forget it"> t;

: Or maybe a a string literal isn't an expression ?

It is an expression, but not a constant-expression.

: Stated otherwise, should I blame Borland or the ARM ?

Neither.

: Thanks for input.

: PS: Would you please mail me a copy of your answer (if any), there's so much
: traffic in this conference I could easily miss it. Didier
: PPS: Sorry if it's a FAQ, it's not on my version of the list.

-- Linc Madison   *   Oakland, California   *   LincMad@Netcom.com




Author: jamshid@castro.uucp (Jamshid Afshar)
Date: Thu, 14 Apr 1994 18:10:14 GMT
Raw View
In article <lincmadCo6t6p.1M1@netcom.com>,
Linc Madison <lincmad@netcom.com> wrote:
>Didier Frick (didier@pax.eunet.ch) wrote:
>: template <class c, const char const *n> class TplTxt { }
                                 ^^^^^-error, maybe you meant to put it
                                 after the *, but there's no real reason to

>: TplTxt<char,"Forget it"> t; // Error
>
>: gives 'Template argument must be a constant expression' when the template
>: is instantiated with Borland C++ 4.0 ?
>
>The string literal "Forget it" is of type char[] (ARM 2.5.4).  ARM 14.2
>requires that any nontype template arguments must be constant-expressions,
>which an object of type char[] is not, even though it meets the "exact
>match with trivial conversions" requirement of ARM 13.2 from char[] to
>const char const *.

I'm not sure what you mean by "even though it meets the exact match
requirement", but in addition to constant-expressions ARM 14.2 allows
nontype template arguments to be addresses of objects or functions
but the object or function must have *external* linkage.  That's why
string literals are not allowed.

Practical problems would be whether Foo<"Hello"> is required to be the
same type as a Foo<"Hello"> used elsewhere in the file or in another
file.  Remember C++ doesn't require the address of identical string
literals to be the same even if they're used in the same module.  I
suppose string literals could have been accepted for template
arguments as a special case and treated more like a "value" than an
address.  The uniqueness of a string could determined by a long
hashing, but the following workaround is acceptable and doesn't
require more rules:

 template <class c, const char *n> class TplTxt { };
 char a[] = "Acceptable";
 TplTxt<char,a> t;

Btw, the string literal workaround suggested in the January Working
Paper is not correct as far as I can tell:

 template<class T, char* p> class X {/*...*/};
 char* p = "Vivisectionist";
 X<int,p> x2;   // ok [not]

That's NOT ok because `p' is not the address of an object with
external linkage, `&p' is.

>: Isn't a literal string a constant expression ? (From what I could understand
>: from the compiler's error messages, it seems to have type char *. In the
>: general case, you could modify the literal, so it seems reasonable. However,
>: to be still more general, I think it could be advisable to provide a way
>: of declaring constant string literals, or to say once and for all that
>: they cannot be modified and so will always be const.)
>
>There is such a mechanism to declare a constant string literal:
>const char const * foo = "Foo string";
>
>Alternately, in your example, you can cast your argument:
>TplTxt<char, (const char const *) "Forget it"> t;

First, your code has a syntax error because both `const's are
modifying `char'.  Second, casting the type of a string literal won't
help because casting won't turn it into an object with external
linkage or into a constant-expression.  Don't confuse the very
specific term constant-expression with the more general `const'.  A
constant-expression is defined in 5.19 as an expression which may only
involve integer arithmetic, integer literals, and `const int'
variables initialized with constant-expressions.  Not even double
literals are constant-expressions so they can't be used as a template
argument (yet?):

 template<class T, T min, T max>
 class Range {/*...*/};

 Range<long, -5454L, 434343243L> l;  // okay

 Range<char*, "AAA", "ZZZ">;         // error

 char aaa[] = "AAA";
 char zzz[] = "ZZZ";
 Range<char*, aaa, zzz>;             // okay

 Range<double, -932.43, 1234.65>;    // error

Jamshid Afshar
jamshid@ses.com




Author: hall_j@sat.mot.com (Joseph Hall)
Date: Fri, 15 Apr 1994 04:12:50 GMT
Raw View
Seems it was lincmad@netcom.com (Linc Madison) who said:
>The string literal "Forget it" is of type char[] (ARM 2.5.4).  ARM 14.2
>requires that any nontype template arguments must be constant-expressions,
>which an object of type char[] is not, even though it meets the "exact
>match with trivial conversions" requirement of ARM 13.2 from char[] to
>const char const *.

It's my understanding that const char const * still is NOT a type
that can appear in a constant-expression.  Pointers, const or otherwise,
are not allowed.

--
Joseph Nathan Hall | Joseph's Law of Interface Design: Never give your users
Software Architect | a choice between the easy way and the right way.
Gorca Systems Inc. |                 joseph@joebloe.maple-shade.nj.us (home)
(on assignment)    | (602) 732-2549 (work)  Joseph_Hall-SC052C@email.mot.com




Author: hall_j@sat.mot.com (Joseph Hall)
Date: Fri, 15 Apr 1994 04:17:56 GMT
Raw View
Seems it was hall_j@sat.mot.com (my idiot twin) who said:
>Seems it was lincmad@netcom.com (Linc Madison) who said:
>>The string literal "Forget it" is of type char[] (ARM 2.5.4).  ARM 14.2
>>requires that any nontype template arguments must be constant-expressions,
>>which an object of type char[] is not, even though it meets the "exact
>>match with trivial conversions" requirement of ARM 13.2 from char[] to
>>const char const *.
>
>It's my understanding that const char const * still is NOT a type
>that can appear in a constant-expression.  Pointers, const or otherwise,
>are not allowed.

Of course I meant

 const char * const

<sigh>

--
Joseph Nathan Hall | Joseph's Law of Interface Design: Never give your users
Software Architect | a choice between the easy way and the right way.
Gorca Systems Inc. |                 joseph@joebloe.maple-shade.nj.us (home)
(on assignment)    | (602) 732-2549 (work)  Joseph_Hall-SC052C@email.mot.com




Author: jason@cygnus.com (Jason Merrill)
Date: Sat, 16 Apr 1994 09:19:37 GMT
Raw View
>>>>> Joseph Hall <hall_j@sat.mot.com> writes:

> It's my understanding that const char const * still is NOT a type
> that can appear in a constant-expression.  Pointers, const or otherwise,
> are not allowed.

Actually, some pointers are allowed:

2 Non-type    template-arguments  must  be     constant-expressions   or  |
  addresses   of   objects  or  functions  with  external  linkage.   In  |
  particular, a string literal (2.9.4) is  not  an  acceptable  template  |
  argument  because  a  string  literal is the address of an object with  |
  static linkage.

Jason




Author: didier@pax.eunet.ch (Didier Frick)
Date: Mon, 11 Apr 1994 21:37:22 GMT
Raw View
Is anybody out there able to explain why the following :

template <class c, int v> class TplInt
{
}

TplInt<char,10> i;

is valid, while:

template <class c, const char const *n> class TplTxt
{
}

TplTxt<char,"Forget it"> t; // Error

gives 'Template argument must be a constant expression' when the template
is instantiated with Borland C++ 4.0 ?

Isn't a literal string a constant expression ? (From what I could understand
from the compiler's error messages, it seems to have type char *. In the
general case, you could modify the literal, so it seems reasonable. However,
to be still more general, I think it could be advisable to provide a way
of declaring constant string literals, or to say once and for all that
they cannot be modified and so will always be const.)

Or maybe a a string literal isn't an expression ?

Stated otherwise, should I blame Borland or the ARM ?

Thanks for input.

PS: Would you please mail me a copy of your answer (if any), there's so much
traffic in this conference I could easily miss it.              Didier

PPS: Sorry if it's a FAQ, it's not on my version of the list.