Connecting Tech Pros Worldwide Forums | Help | Site Map

Isn't 'std:.string::npos' an integral constant?

Hendrik Schober
Guest
 
Posts: n/a
#1: Sep 19 '08
Hi,

this
#include <string>
class test {
typedef std::string::size_type size_type;
static const size_type x = std::string::npos;
};
doesn't compile using either VC9 ("expected constant expression")
or Comeau Online ("constant value is not known"). If I replace
'std::string::npos' by '-1' it compiles.
Why isn't 'std::string;::npos' a "known constant expression"? What
am I missing?

TIA;

Schobi

Victor Bazarov
Guest
 
Posts: n/a
#2: Sep 19 '08

re: Isn't 'std:.string::npos' an integral constant?


Hendrik Schober wrote:
Quote:
this
#include <string>
class test {
typedef std::string::size_type size_type;
static const size_type x = std::string::npos;
};
doesn't compile using either VC9 ("expected constant expression")
or Comeau Online ("constant value is not known"). If I replace
'std::string::npos' by '-1' it compiles.
Why isn't 'std::string;::npos' a "known constant expression"? What
am I missing?
Hard to say. AFAICT, 14.7.1/1 requirements are met, the static data
member 'npos' should be instantiated (and the definition should exist),
and since 'npos' itself was initialised with a const expression, it is
allowed to be used in another const expression (5.19/1). Seems like a
bug in both compilers.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Paavo Helde
Guest
 
Posts: n/a
#3: Sep 22 '08

re: Isn't 'std:.string::npos' an integral constant?


Hendrik Schober <spamtrap@gmx.dekirjutas:
Quote:
Hi,
>
this
#include <string>
class test {
typedef std::string::size_type size_type;
static const size_type x = std::string::npos;
};
doesn't compile using either VC9 ("expected constant expression")
or Comeau Online ("constant value is not known"). If I replace
'std::string::npos' by '-1' it compiles.
Why isn't 'std::string;::npos' a "known constant expression"? What
am I missing?
Integral const expressions are usuful mostly for declaring C-style array
sizes and for template specialization. Most probably you never want to
declare an array of std::string::npos elements. OTOH, it may be imaginable
that you want to specialize a template with that value, but I guess this
was not considered a sufficiently sound reason to require std::string::npos
to be a const expression.

Paavo

Hendrik Schober
Guest
 
Posts: n/a
#4: Sep 22 '08

re: Isn't 'std:.string::npos' an integral constant?


James Kanze wrote:
Quote:
On Sep 20, 8:56 pm, Hendrik Schober <spamt...@gmx.dewrote:
[...]
Quote:
> For one, there's 5.19 which says:
> "An integral constant expression can involve [...]
> static data members of integral or enumeration types
> [...]."
> So it seems that a static data member of integral type
> is a constant integral expression.
>
Not necessarily. You cut part of the requirements. The
essential parts read "An integral constant expression can
involve [...]const variables or static data members of integral
or enumeration types initialized with constant
expressions,[...]" It's quite clear that the "or" between
"variables" and "static data members" joins just those two
nominal groups; that everything else (const, initialized with
constant expressions) applies to both. [...]
(Is it? Well, did I say I dread having to read the standard?)
Quote:
Quote:
> Then there's 9.4.2/4:
> "If a static data member is of const integral or const
> enumeration type, its declaration in the class
> definition can specify a constant initializer which
> shall be an integral constant expression (5.19)."
> The way I read this, my 'test::x', which is of integral
> type, can be initialized in-class, if I use a constant
> integral expression.
>
It can be. Yes.
>
Quote:
> Finally, 21.3 shows 'std::basic_string<T>::npos' as
> static const size_type npos = -1;
> (which is the only thing I was able to find resembling
> a definition of what it should be).
>
And this is where it is unclear. How significant is the fact
that the value is given in this format? It is obvious that the
standard doesn't require textual identity with its class
definitions, but just what does it require? [...]
It doesn't? I would have thought it does.
Quote:
Quote:
> To me this looks like 'std::string::npos' is defined as
> being '-1', which would make it an integral constant
> definition, which in turn means it could be used to
> initialize constant static data member of integral type.
> Which I thought I tried to do.
>
Quote:
> I'm sure I missed something along the way (for example,
> I have no idea what 14.7.1 has to do with all this), but
> I wouldn't know what.
>
The real question is whether the initializer of npos is visible
when you want to use it as an integral constant expression. I
would sort of expect it to be in most implementations, because
this seems like the simplest way of doing it. But I'm far from
sure that it is required.
In VC9's implementation (Dinkumware), 'npos' is initialized
after the class template's definition. But so it was in VC71
(Dinkumware, too), where th same code used to compile...

Anyway, thanks for taking the time to explain.

Schobi
Hendrik Schober
Guest
 
Posts: n/a
#5: Sep 22 '08

re: Isn't 'std:.string::npos' an integral constant?


Paavo Helde wrote:
Quote:
Hendrik Schober <spamtrap@gmx.dekirjutas:
>
Quote:
>Hi,
>>
>this
> #include <string>
> class test {
> typedef std::string::size_type size_type;
> static const size_type x = std::string::npos;
> };
>doesn't compile using either VC9 ("expected constant expression")
>or Comeau Online ("constant value is not known"). If I replace
>'std::string::npos' by '-1' it compiles.
>Why isn't 'std::string;::npos' a "known constant expression"? What
>am I missing?
>
Integral const expressions are usuful mostly for declaring C-style array
sizes and for template specialization. Most probably you never want to
declare an array of std::string::npos elements. OTOH, it may be imaginable
that you want to specialize a template with that value, but I guess this
was not considered a sufficiently sound reason to require std::string::npos
to be a const expression.
In my case it was some open source lib which, for reasons I haven't
looked into, introduced its own string class while depending on
'std::string' to supply its 'npos' value...
Quote:
Paavo
Schobi
James Kanze
Guest
 
Posts: n/a
#6: Sep 23 '08

re: Isn't 'std:.string::npos' an integral constant?


On Sep 22, 11:50 pm, Paavo Helde <nob...@ebi.eewrote:
Quote:
Hendrik Schober <spamt...@gmx.dekirjutas:
Quote:
Interestingly, Comeau compile this
struct test1 {
static const int x = -1;
};
>
Quote:
struct test2 {
static const int x = test1::x;
};
without any complaints. However, it compiles this
struct test1 {
static const int x;
};
const int test1::x = 1;
>
Quote:
struct test2 {
static const int x = test1::x;
};
just as well.
Quote:
Indeed. However, if test1 is a template, it fails. Seems a bit
inconsistent.
Not really. A template definition is not a variable definition;
only the instantiation of a template definition is a variable
definition. And the "point of instantiation" of a member
function or member static variable is immediately following the
namespace scope declaration which triggers the instantiation.
So if you write:

template< typename T >
struct test1
{
static int const x ;
} ;

template< typename T >
int const test1::x = 1 ;

struct test2
{
static int const x = test1< int >::x ;
} ;

, the compiler inserts the instantiation of the class test1<int>
immediately before the definition of test2, and the
instantiation of the static data member immediately after, i.e.:

struct test1< int >
{
static int const x ;
} ;

struct test2
{
static int const x = test1< int >::x ;
} ;
int const test1< int >::x = 1 ;

And the value of test1< int >::x isn't visible when test2::x is
declared.

--
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
Pete Becker
Guest
 
Posts: n/a
#7: Sep 23 '08

re: Isn't 'std:.string::npos' an integral constant?


On 2008-09-23 03:45:08 -0400, James Kanze <james.kanze@gmail.comsaid:
Quote:
>
Out of curiousity, I generated the preprocessor output for a
program consisting of just an #include <string>, for all of the
compiler/library combinations I have available. None seem to
have an explicit specialization. They split with regards to
where npos is initialized, with those that initialize it in the
class never providing a declaration (which results in undefined
behavior if you use it in a context where the object is
required---but compilers can defined undefined behavior).
And the implementation of the standard library does not have to be
written in portable C++, something which even members of the standards
committee have to be reminded of.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

James Kanze
Guest
 
Posts: n/a
#8: Sep 23 '08

re: Isn't 'std:.string::npos' an integral constant?


On Sep 23, 2:20 pm, Pete Becker <p...@versatilecoding.comwrote:
Quote:
On 2008-09-23 03:45:08 -0400, James Kanze <james.ka...@gmail.comsaid:
Quote:
Out of curiousity, I generated the preprocessor output for a
program consisting of just an #include <string>, for all of
the compiler/library combinations I have available. None
seem to have an explicit specialization. They split with
regards to where npos is initialized, with those that
initialize it in the class never providing a declaration
(which results in undefined behavior if you use it in a
context where the object is required---but compilers can
defined undefined behavior).
Quote:
And the implementation of the standard library does not have
to be written in portable C++, something which even members of
the standards committee have to be reminded of.
That was more or less what I meant to imply with my comment in
parentheses. In this case, the implementation of
std::basic_string in the g++ library clearly contains undefined
behavior, according to the standard. But it works with g++,
because of what the compiler does in this particular case, and
that's all that matters; it's not an error in the library.

--
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
Closed Thread