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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Hendrik Schober

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

    Hi,

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

    TIA;

    Schobi
  • Victor Bazarov

    #2
    Re: Isn't 'std:.string::n pos' an integral constant?

    Hendrik Schober wrote:
    this
    #include <string>
    class test {
    typedef std::string::si ze_type size_type;
    static const size_type x = std::string::np os;
    };
    doesn't compile using either VC9 ("expected constant expression")
    or Comeau Online ("constant value is not known"). If I replace
    'std::string::n pos' 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

    Comment

    • Paavo Helde

      #3
      Re: Isn't 'std:.string::n pos' an integral constant?

      Hendrik Schober <spamtrap@gmx.d ekirjutas:
      Hi,
      >
      this
      #include <string>
      class test {
      typedef std::string::si ze_type size_type;
      static const size_type x = std::string::np os;
      };
      doesn't compile using either VC9 ("expected constant expression")
      or Comeau Online ("constant value is not known"). If I replace
      'std::string::n pos' 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::np os 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::np os
      to be a const expression.

      Paavo

      Comment

      • Hendrik Schober

        #4
        Re: Isn't 'std:.string::n pos' an integral constant?

        James Kanze wrote:
        On Sep 20, 8:56 pm, Hendrik Schober <spamt...@gmx.d ewrote:
        [...]
        > 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?)
        > 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.
        >
        > Finally, 21.3 shows 'std::basic_str ing<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.
        > To me this looks like 'std::string::n pos' 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.
        >
        > 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

        Comment

        • Hendrik Schober

          #5
          Re: Isn't 'std:.string::n pos' an integral constant?

          Paavo Helde wrote:
          Hendrik Schober <spamtrap@gmx.d ekirjutas:
          >
          >Hi,
          >>
          >this
          > #include <string>
          > class test {
          > typedef std::string::si ze_type size_type;
          > static const size_type x = std::string::np os;
          > };
          >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::np os 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::np os
          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...
          Paavo
          Schobi

          Comment

          • James Kanze

            #6
            Re: Isn't 'std:.string::n pos' an integral constant?

            On Sep 22, 11:50 pm, Paavo Helde <nob...@ebi.eew rote:
            Hendrik Schober <spamt...@gmx.d ekirjutas:
            Interestingly, Comeau compile this
            struct test1 {
            static const int x = -1;
            };
            >
            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;
            >
            struct test2 {
            static const int x = test1::x;
            };
            just as well.
            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.kan ze@gmail.com
            Conseils en informatique orientée objet/
            Beratung in objektorientier ter Datenverarbeitu ng
            9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

            Comment

            • Pete Becker

              #7
              Re: Isn't 'std:.string::n pos' an integral constant?

              On 2008-09-23 03:45:08 -0400, James Kanze <james.kanze@gm ail.comsaid:
              >
              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)

              Comment

              • James Kanze

                #8
                Re: Isn't 'std:.string::n pos' an integral constant?

                On Sep 23, 2:20 pm, Pete Becker <p...@versatile coding.comwrote :
                On 2008-09-23 03:45:08 -0400, James Kanze <james.ka...@gm ail.comsaid:
                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.
                That was more or less what I meant to imply with my comment in
                parentheses. In this case, the implementation of
                std::basic_stri ng 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.kan ze@gmail.com
                Conseils en informatique orientée objet/
                Beratung in objektorientier ter Datenverarbeitu ng
                9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                Comment

                Working...