Topic: Case for a native associative array?


Author: Ian Collins <ian-news@hotmail.com>
Date: Mon, 6 Feb 2006 12:17:18 CST
Raw View
Having been using PHP alongside C++ for a while, I have found the PHP
ability to declare and statically initialise an associative array (map
in C++ terms) very useful.

Do  people think the ability to initialise a map would be a worthwhile
addition to C++?

--
Ian Collins.

---
[ 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: "Aaron Graham" <atgraham@gmail.com>
Date: Mon, 6 Feb 2006 13:52:32 CST
Raw View
Ian Collins wrote:
> Having been using PHP alongside C++ for a while, I have found the PHP
> ability to declare and statically initialise an associative array (map
> in C++ terms) very useful.
>
> Do  people think the ability to initialise a map would be a worthwhile
> addition to C++?

Stroustrup talks briefly about the goal of generalization of
initializers in the upcoming C++0x here:
http://public.research.att.com/~bs/DnE2005.pdf (see Section 4.2)

Though he doesn't mention std::map specifically, he does give an
example using std::vector.

Aaron

---
[ 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: John Nagle <nagle@animats.com>
Date: Mon, 6 Feb 2006 22:09:37 CST
Raw View
Aaron Graham wrote:
> Ian Collins wrote:

> Stroustrup talks briefly about the goal of generalization of
> initializers in the upcoming C++0x here:

   You can write a constructor with a variable
number of arguments, using the "stdarg" mechanism.
This yields a syntactically nice initialization construct.
See the example below, and note the line that reads

      table tab("Hello", "World");

   That's a true N-argument constructor.  It's not clear
that the Standard allows this, but it does work in,
at least, Visual C++.

   Of course, this has all the usual limitations of the "stdarg"
mechanism - no type checking, and ambiguity detecting the
end of the argument set when the argument is not a pointer.
But if "stdarg" could be improved a bit, this would be a
viable construct.

   Traditionally, "stdarg" has the absolute minimum functionality
needed to implement "printf", but that's not fundamental.

    John Nagle
    Animats

#include <vector>
#include <string>
#include <stdarg.h>
#include <stdio.h>

class table {
private:
 std::vector<std::string> m_values;
public:
 table(const char* args, ...);
 size_t size() { return(m_values.size()); }
 const std::string& operator[](size_t i) const { return(m_values[i]); }
};
// Constructor with variable number of arguments
table::table(const char* arg, ...)
{
 va_list ap;
 va_start(ap, arg);
 while (arg) // for all args
 {   m_values.push_back(arg);
  arg = va_arg(ap, const char*);
 }
 va_end(ap);
}
//
// demotable -- demo the table type
//
void demotable()
{
 table tab("Hello", "World"); // variable length constructor
 printf("Table has %d entries.\n", tab.size());
 for (size_t i=0; i<tab.size(); i++)
 { printf("tab[%d] = %s\n", i, tab[i].c_str()); }
}

---
[ 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: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 7 Feb 2006 04:09:00 GMT
Raw View
Ian Collins ha scritto:
>
> Having been using PHP alongside C++ for a while, I have found the PHP
> ability to declare and statically initialise an associative array (map
> in C++ terms) very useful.
>
> Do  people think the ability to initialise a map would be a worthwhile
> addition to C++?
>

(As I believe it might cause misunderstanding, I'm going to use the
terms "static initialization" with the meaning described in 3.6.2/1,
which is probably different from what you intend.)

Static initialization (i.e.: as for PODs) for a map is simply impossible
because a map handles objects allocated on the heap. Even if it were
possible, it would require a stricter coupling between the compiler and
the library, which we don't have now and we don't want. A conformant C++
compiler is expected to be able to compile and use any reasonable
implementation of std::map, not only the one with which it is shipped.
If we had static initialization then most probably the programmer would
be stuck with the compiler-preferred implementation. Imagine... in 2002
I would be forced to use the broken VC6 STL implementation instead of
STLport... what a nightmare!

About dynamic initialization, there is a library-based approach called
Boost.Assign <http://boost.org/libs/assign/doc/index.html> that could be
used. It could be wrapped in macros to make its use more convenient for
global objects.

I have also read somewhere that there's ongoing work to consider some
kind of {}-syntax in constructor calls, but I don't know much more.

However, good C++ programming style is to avoid, when possible, global
objects and prefer the singleton pattern, especially when complex
initialization is required.

Regards,

Ganesh

---
[ 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: cbarron3@ix.netcom.com (Carl Barron)
Date: Tue, 7 Feb 2006 02:15:10 CST
Raw View
John Nagle <nagle@animats.com> wrote:

>
>    You can write a constructor with a variable
> number of arguments, using the "stdarg" mechanism.
> This yields a syntactically nice initialization construct.
> See the example below, and note the line that reads
>
>       table tab("Hello", "World");
  This will load one const char * in your class example not quoted.. It
is not typesafe and requires a dummy argument to the constructor. I pity
the poor soul that does
   table foo("x",4,3,4,9);  :):)
safer is to provide append via operator << () although it takes a
constructor and a line to initailize.

  table foo
  foo << "Hello" << "World";
  can be type safe and it can in effect do what the stdarg convolutions
do in your constructor.  If you need an arbitrary # of args for a
constructor then it is probably
loading a container at some point in the arg list and continuing until
end of list.
  table & operator << (table & t,const char *s)
  {
      t.insert(s); //or make this function a friend
                  // and directly access the vector.
      return t;
  }


---
[ 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: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 7 Feb 2006 23:18:27 GMT
Raw View
John Nagle ha scritto:
>
>      table tab("Hello", "World");
>
>   That's a true N-argument constructor.  It's not clear
> that the Standard allows this, but it does work in,
> at least, Visual C++.

The problem is that the constructor cannot portably determine the number
of arguments. See below.

> //    Constructor with variable number of arguments
> table::table(const char* arg, ...)
> {
>     va_list ap;
>     va_start(ap, arg);
>     while (arg)    // for all args
>     {   m_values.push_back(arg);
>         arg = va_arg(ap, const char*);
>     }
>     va_end(ap);
> }

This code invokes undefined behaviour. About the use of macro va_arg()
the C standard is normative and says in 7.15.1.1: "If there is no actual
next argument [...] the behavior is undefined, [...]." The fact that, on
Visual C++, va_arg() might return 0 at the end of the argument list is
therefore a non-portable fact. I'm prone to believe that also on VC++ it
is an unintended accident, rather than a feature.

Regards,

Ganesh

---
[ 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: nagle@animats.com (John Nagle)
Date: Wed, 8 Feb 2006 04:00:43 GMT
Raw View
Carl Barron wrote:
> John Nagle <nagle@animats.com> wrote:
>
>
>>   You can write a constructor with a variable
>>number of arguments, using the "stdarg" mechanism.
>>This yields a syntactically nice initialization construct.
>>See the example below, and note the line that reads
>>
>>      table tab("Hello", "World");
>
>   This will load one const char * in your class example not quoted.. It
> is not typesafe and requires a dummy argument to the constructor.

    The example actually runs correctly in Microsoft Visual
C++ 6.0.  Should it fail, according to the standard? If
so, why?

> I pity
> the poor soul that does
>    table foo("x",4,3,4,9);

    I agree that it is not type-safe.  That's really a problem
with the "stdarg" mechanism.  Perhaps fixing the "stdarg"
mechanism is indicated.  Now that C++ has more machinery for
talking about types, it may be possible to fix "stdarg".

    We might even be able to make the "printf" family checkable at run
time in a standard way, which would not be a bad thing.

   John Nagle
   Animats

---
[ 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: cbarron413@adelphia.net (Carl Barron)
Date: Wed, 8 Feb 2006 15:31:35 GMT
Raw View
In article <_S5Gf.30727$H71.13235@newssvr13.news.prodigy.com>, John
Nagle <nagle@animats.com> wrote:

>    The example actually runs correctly in Microsoft Visual
> C++ 6.0.  Should it fail, according to the standard? If
> so, why?
  As I recall the inards of va_list is implimentation defined, The
standards [C++,C89,C99] only specify the effects of the various
va_* macros/types.  Among the standard va_* macros there is no
end sentiel of a va_list. It might not have one! In fact it might be
a simple typedef like:
   typedef void *va_list;
and an accident that it ends when it contains zero.

---
[ 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: nagle@animats.com (John Nagle)
Date: Wed, 8 Feb 2006 19:32:10 GMT
Raw View
Alberto Ganesh Barbati wrote:
> John Nagle ha scritto:
>
>>     table tab("Hello", "World");
>>
>>  That's a true N-argument constructor.  It's not clear
>>that the Standard allows this, but it does work in,
>>at least, Visual C++.
>
>
> The problem is that the constructor cannot portably determine the number
> of arguments. See below.

> This code invokes undefined behaviour. About the use of macro va_arg()
> the C standard is normative and says in 7.15.1.1: "If there is no actual
> next argument [...] the behavior is undefined, [...]." The fact that, on
> Visual C++, va_arg() might return 0 at the end of the argument list is
> therefore a non-portable fact. I'm prone to believe that
> also on VC++ it is an unintended accident, rather than a feature.

    That is correct.  It's a Microsoft "extension".

    The real problem is that C++ does functions with
variable numbers of arguments rather badly.  That might
be worth fixing.  What we have now is a legacy mechanism
from K&R C.  It's not type-safe, and it's a source of
security holes.  (Ref: http://linux.sys-con.com/read/158825.htm)

    We do have the advantage in C++ that the compiler knows,
both when compiling the definition of the function and
the call to the function, that a function with a variable
number of arguments is being compiled.  So there is the
option of providing run-time type information for this
case.  That might be worth considering.  It would
certainly be better than what we have now.

    With some means of obtaining the argument count and
the argument types at run time, va_arg, and the
entire "printf" family, could be made typesafe.  That would
be worth doing.

    John Nagle
    Animats

---
[ 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: kuyper@wizard.net
Date: Wed, 8 Feb 2006 13:34:20 CST
Raw View
John Nagle wrote:
.
>     We might even be able to make the "printf" family checkable at run
> time in a standard way, which would not be a bad thing.

As I understand it, C++ already has the fix: it involves using
templates and operator overloading instead of format strings to achieve
type safety, and it's called iostreams. Sometimes the problems with one
interface are so fundamental that the best fix is not to make minor
fixes to that interface, but to change to a fundamentally quite
different interface.

---
[ 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                       ]