On Nov 17, 10:45 pm, Alberto Ganesh Barbati
wrote:
> Boris Rasin ha scritto:
>
>
>
> > On Nov 14, 6:09 pm, Mathias Gaunard
> >> On 14 nov, 00:31, Boris Rasin
>
> >>> template
> >>> class store
> >>> {
> >>> public:
> >>> store (Args ... args) : members (args) ... {}
> >>> void forward() { some_func (members ...); }
> >>> Args ... members; // Error: template parameter pack expansion
not
> >>> supported in this context. Why not?
> >> What could it do?
> >> Try tuple
>
> > Like I said, I want (perfect) forwarding at a later stage (see
> > "forward" member function in my sample). And "tuple
> > wouldn't work.
>
> All you need is an helper function like this:
>
> template
> /* whatever */ invoke(T f, tuple
>
> which calls f with the supplied arguments. It should not be too
> difficult to make it a perfect forwarder.
>
> Ganesh
Seeing that it should not be too difficult, would you mind actually
showing how to call a function with any number of parameters given
tuple<> object as parameter container (as in your sample)? No need to
make it a perfect forwarding, just anything that would actually work.
Thank you very much.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Variadic templates
Pointers, auto-pointers, etc.
robean wrote:
> I am trying to get together a bunch of code-samples for interviews,
> and have been advised to keep them short (300 - 500 lines, approx.).
> Can anyone suggest such a short project that explicitly uses
> pointers? Obviously, with the vast offerings of the Standard
> Libraries, one ends up using pointers *under the hood*, but I'm
> looking for something that would require a fair bit of explicit low-
> level manipulation. Any ideas?
This example code is using a virtual function to polymorphically invoke the
copy-constructor. This can be used to copy an object while only having a
pointer or reference to the base instead of the complete type.
struct base
{
virtual ~base() {}
virtual base* clone() const = 0;
};
struct derived1: base
{
virtual derived1* clone() const
{ return new derived1(*this); }
};
struct derived2: base
{
virtual derived2* clone() const
{ return new derived2(*this); }
};
Give them this sample code and ask them to improve it using std::auto_ptr.
Actually, there are lots of ways this code can be improved, and some will
be easy when touching the code anyway.
Solutions in the next days, unless anyone else wants to jump in. ;)
Uli
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Virtual Base Class, "Diamond" Inheritance
On 1 Dez., 20:05, Ryan Clark
> I'm getting a little frustrated with constructor syntax when I use
> virtual base classes.
>
> Take the following code (classic diamond inheritance):
>
> class BaseClass
> {
> int base_value;
> public:
>
> BaseClass(int bv) : base_value(0)
> {
> base_value = bv;
> }
This initialization of member base_value looks a bit silly
to me, why did you not use the member initializer list for
that?
> virtual ~BaseClass()
> {
> }
>
> int value() const
> {
> return base_value;
> }
> };
>
> class A : public virtual BaseClass
> {
> public:
> A() : BaseClass(1)
> {
> }
>
> virtual ~A()
> {
> }
> };
You can remove all the empty virtual destructor definitions
on the sub-class-hierarchies of BaseClass, because virtually
derived classes honor virtual member functions of base classes,
see 10.3 [class.virtual]/2 (All my standard references are
relative to the recent draft N2798). Therefore I removed them
in my following quotes.
> class B : public virtual BaseClass
> {
> public:
> B() : BaseClass(2)
> {
> }
[..]
> };
>
> class Diamond: public A, public B
> {
> public:
> Diamond(): BaseClass(3)
> {
> }
[..]
> };
>
> int main(int argc, char* argv[])
> {
> Diamond d;
>
> printf("Hello World! %d\n", d.value());
> return 0;
> }
>
> This code won't compile without the calls to the BaseClass constructor
> in A and B, even though they are never called. Why is that? I have
> already told the compiler, "this class will be instantiated somewhere
> else" (right?), why do I have to add completely meaningless code to
> make the compiler happy?
No, you did *not* tell the compiler that A and B might never be
instantiated, because they are instantiable. Just add the definition
A a;
immediately after the definition of A and you have a valid object
definition.
> What's more... if add this class:
>
> class Diamond2 : public Diamond
> {
> public:
> Diamond2(): BaseClass(4)
> {
> }
[..]
> };
>
> And change variable d to type Diamond2, it won't compile without the
> constructor call to BaseClass. It seems to me that the call to
> BaseClass should be satisfied by the call in the Diamond constructor.
No, it is not, because a virtual base class is constructed in the
most derived object, see 10.1 [class.mi]/4:
"[..] For each distinct base class that is specified virtual, the
most derived object shall contain a single base class subobject
of that type.[..]"
and 12.6.2 [class.base.init]/7:
"All subobjects representing virtual base classes are initialized
by the constructor of the most derived class (1.8). If the
constructor of the most derived class does not specify a mem-
initializer for a virtual base class V, then Vs default
constructor is called to initialize the virtual base class
subobject. If V does not have an accessible default constructor,
the initialization is ill-formed. A mem-initializer naming a
virtual base class shall be ignored during execution of the
constructor of any class that is not the most derived class."
> I have two problems with this, (1) code is getting duplicated
> unnecessarily, and (2) it undermines the programmer's ability to
> design neatly encapsulated classes (for example, if the whole purpose
> of class Diamond was to set the correct value in BaseClass).
>
> Is there something I'm missing? I might be less frustrated if I had a
> better understanding about what is going on. I don't see any
> explanation in Stroustrup. Is there some kind of syntactic trick I can
> use to duplicate less code?
You are not the first one who stumbled across this problem, see
e.g. the recent thread "Initialization of base virtual classes":
http://preview.tinyurl.com/6anord
The point is, that the virtual base class-c'tor is invoked
in the most derived object. Which one this is, depends on the
actual object. In your example all types A, B, Diamond, and
Diamond2 can be instantiated, so it makes sense to add the
c'tors in *all* classes. There is one situation, where this
requirement really annoys and that are *abstract* base classes
(which can never be instantiated). here is still an active
issue lurking around:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#257
which attempts to solve this problem for this special use-case
(which is not relevant for your example).
HTH & Greetings form Bremen,
Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Virtual Base Class, "Diamond" Inheritance
On Dec 1, 2:05 pm, Ryan Clark
> Hello,
>
> I'm getting a little frustrated with constructor syntax when I use
> virtual base classes.
>
> Take the following code (classic diamond inheritance):
>
> class BaseClass
> {
> int base_value;
> public:
>
> BaseClass(int bv) : base_value(0)
> {
> base_value = bv;
> }
>
> virtual ~BaseClass()
> {
>
> }
>
> int value() const
> {
> return base_value;
> }
>
> };
>
> class A : public virtual BaseClass
> {
> public:
> A() : BaseClass(1)
> {
> }
>
> virtual ~A()
> {
>
> }
>
> };
>
> class B : public virtual BaseClass
> {
> public:
> B() : BaseClass(2)
> {
> }
>
> virtual ~B()
> {
>
> }
>
> };
>
> class Diamond: public A, public B
> {
> public:
> Diamond(): BaseClass(3)
> {
>
> }
>
> virtual ~Diamond()
> {
>
> }
>
> };
>
> int main(int argc, char* argv[])
> {
> Diamond d;
>
> printf("Hello World! %d\n", d.value());
> return 0;
>
> }
>
> This code won't compile without the calls to the BaseClass constructor
> in A and B, even though they are never called. Why is that? I have
> already told the compiler, "this class will be instantiated somewhere
> else" (right?), why do I have to add completely meaningless code to
> make the compiler happy?
>
> What's more... if add this class:
>
> class Diamond2 : public Diamond
> {
> public:
> Diamond2(): BaseClass(4)
> {
> #include
class BaseClass
{
int base_value;
public:
BaseClass(int bv = 0) : base_value(bv)
{
}
virtual ~BaseClass() { }
int value() const { return base_value; }
};
class A : public virtual BaseClass
{
public:
A() { }
~A() { }
};
class B : public virtual BaseClass
{
public:
B() { }
~B() { }
};
class Diamond: public A, public B
{
public:
Diamond(): BaseClass(3) { }
~Diamond() { }
};
int main(int argc, char* argv[])
{
Diamond d;
std::cout << "d.value() is ";
std::cout << d.value() << std::endl;
}
> }
>
> virtual ~Diamond2()
> {
>
> }
>
> };
>
> And change variable d to type Diamond2, it won't compile without the
> constructor call to BaseClass. It seems to me that the call to
> BaseClass should be satisfied by the call in the Diamond constructor.
BaseClass doesn't have a default ctor. Therefore classes A and B
require the presence of a parametized ctor even though type Diamond
will invoke that parametized BaseClass ctor.
The issue is not whether the Diamond ctor 'satisfies' the
initialization of its base classes. The program has no choice but to
guarentee that an instance of A or B is properly generated. Its that
simple.
The above code says "BaseClass is not default constructeable". Why
should the program assume otherwise?
To correct the issue, provide a default ctor:
#include
class BaseClass
{
int base_value;
public:
BaseClass(int bv = 0) : base_value(bv)
{
}
virtual ~BaseClass() { }
int value() const { return base_value; }
};
class A : public virtual BaseClass
{
public:
A() { }
~A() { }
};
class B : public virtual BaseClass
{
public:
B() { }
~B() { }
};
class Diamond: public A, public B
{
public:
Diamond(): BaseClass(3) { }
~Diamond() { }
};
int main(int argc, char* argv[])
{
Diamond d;
std::cout << "d.value() is ";
std::cout << d.value() << std::endl;
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
c++0x attributes
On Nov 30, 6:16 pm, german diago
> Hello everyone.
>
> My question is very simple. Will c++0x attributes user-extensible?
The C++0x attributes is the standardization of GNU __attribute__ and
MS __declspec() constructs. There are 3 standard attributes: align,
noreturn, final. Other attributes will be vendor/compiler specific.
As I understand it, C++ programmers will not be able to introduce new
attributes.
Rgds,
anna
--
http://missingrainbow.blogspot.com
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Rationale of non-const reference to temporaries
On 1 Dez., 20:52, eca
> I would like to submit the following code to your attention:
>
> #include
> #include
>
> void f(std::string& s)
> { std::cout << s << std::endl; }
>
> int main(int argc, char* argv[])
> {
> std::string s("Hello world");
> f(s); // <- This is ok
> f(std::string("Hello world")); // <- This is incorrect (g++)
> return 0;
> }
>
> It compiles without errors on VC++ 8.0 (2005), while on gcc 4.1.2
> (and later) it gives the following error:
>
> g++ -O2 -g -Wall -fmessage-length=0 -c -o main.o main.cpp
> main.cpp: In function 'int main(int, char**)':
> main.cpp:11: error: invalid initialization of non-const reference of
> type 'std::string&' from a temporary of type 'std::string'
> main.cpp:4: error: in passing argument 1 of 'void f(std::string&)'
> make: *** [main.o] Error 1
>
> What I know is that temporaries can be passed as const references
> and that VC allows passing them as non-const references as an
> extension to the standard.
> What I don't know precisely is whether there is any potential risk
> of error in doing as above.
>
> Could you help me understand the rationale of the two approaches?
Let me first add that you can enforce the VC compiler to
use the standard-conforming behavior to reject your code
example by activating the "Disable language extensions"
mode (Add /Za).
The reason why standard C++ decided the rules is to provide
a safety belt for you: Usually an object addressed per mutable
lvalue reference as above is supposed to modify this thingee
and that this changed state in this thingee can be evaluated
later. Now consider the following example, which was the
showstopper for allowing rvalues (like temporaries) to be
acceptable arguments for lvalue-references:
void inc(int& arg) { arg++; }
typedef long MyInt;
int main() {
MyInt i = 0;
inc(i);
if (i == 1) {
// Life-saving logic
}
}
Should this program be well-formed? If yes, how do you
estimate the chances, that this kind of *error* - hidden
in some complex software, will be finally found and fixed?
What happens in my example is that i is converted into
a *temporary* of type int, which is the actual argument
of inc. So, the seemingly induced change i never happens,
because *only* the temporary itself is modified here!
And this kind of code example was the reason, why C++
decided for the current rules in this regard.
Now, as your example implies: Sometimes we would really
like the behavior, that the compiler accepts a temporary
as a mutable references (e.g. in those cases, where we
are not interested in the final result of the temporary.
C++0x added so-called rvalue-references which would
make your snippet well-formed:
#include
#include
void f(std::string&& s) // <- Note the && here!
{ std::cout << s << std::endl; }
int main(int argc, char* argv[])
{
std::string s("Hello world");
f(s); // <- This is ok
f(std::string("Hello world")); // <- This is *now* also ok!
return 0;
}
HTH && Greetings from Bremen,
Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Exception specifications unfortunate, and what about their future?
> Once again, this doesn't follow. You can plug the Boehm collector into C++
> and yet have destructors. What you cannot have is deterministic
> destruction for garbage collected *objects*, since, by design, garbage
> collection is non-deterministic from the perspective of the collector's
> user. However, the presence of a garbage collector does not mean all
> objects have to be garbage collected. This is only the case with Java, the
> designers of which decided to do away with automatic objects. In
> principle, there is no technical reasaon against garbage-collected and
> automatic objects existing side-by-side.
Of course it is technically possible to create a GC and let it manage
memory. There is nothing to prevent you. Admitted, I base my statement on
the fact that a GC in a C++ software system is not a commonly used idiom.
The common case is to use deterministic destruction an dtors.
Notice, also it is well possible to use manual memory management in Java
code. Some people even tought operating systems classes in Java. Anyways, I
claim the presence of a GC in its current widely used form implies some form
of manual resource management for closing files and such. Same would be true
for letting a simple Boehm GC manage a file object in C++.
Anyways, this got way beyond my intention to give reasoning why there is no
try-finally build into the C++ language. Also, I certainly agree GCs make
life easier for business objects consisting of some memory with some data in
it. Dtors are better when a type focusses on resource management, i.e. RAII.
Here, we could add C#'s using statements to the soup...
To those who are interested in the topic of GCs there is an interesting
PodCast available at Software Engineering Radio which I found quite
inspiring since it highlight some technological aspects and limitations:
http://www.se-radio.net/podcast/2007-09/episode-68-dan-grossman-garbage-coll
ection-and-transactional-memory
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Template parameter matching for class and class method
On Dec 1, 2:10 pm, Daniel Krügler
wrote:
> I think you provided a really nice solution to the OP's
> problem and I guess the overhead of your implementation
> is remarkably small.
Thanks :) - but it is worth highlighting an important limitation: the
function makeMethod is a constexpr - and that specifier will be
ignored if non-constexpr arguments are provided.
But something along the following lines would work (bind would not
need to be a constexpr fun)
auto m1 = bind(make(&S::foo),s,...);
Also placeholder-support is not provided - which would probably add
some lines of code.
> What I sometimes wish for C++XX is
> a syntax, which prevents the redundancy to provide the
> class name as part of the function pointer specification
> and the additionally provided object. Delphi allows the
> following construct (freely translated into C++) to
> store a closure:
>
> auto m1 = s.bar; // Deduces type of s and binds the
I agree - that would be far more convenient.
> // pair of s and &Type::bar
>
> This syntax does not support parameter binding, but it's
> lack of is one of the annoying things in C++ IMO.
>
Once again - we are in complete agreement.
regards,
Faisal Vali
Radiation Oncology
Loyola
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
A problem with "extern"
On Dec 1, 12:18 pm, Thomas Richter
> drop schrieb:
>
> > I have write a short program that use a static globle variabl .That
> > variable has been modefied in another file, but the result is not as
> > expect,nothing to output to show that variable has been modefied!
>
> "global" is actually not a term that is defined in C or C++.
ISO 2003 C++ standard, 3.3.5 Namespace Scope, subsection 3, defines
the 'global namespace' as the outermost declarative region of a
translation unit, and it says names in the 'global namespace' are said
to be 'global'.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Mapping one set of bits to another
Rick wrote:
[snip]
> I would like to give some compile-time executing template logic a list
> of bits that are set to mean things, and a list of bits that are set
> to mean things in another scheme, and have the templates come up with
> an expression that maps one set of bits into the other set of bits.
> Acceptable limitations in the particular case I need to solve are: 1)
> Bits are "monotonic." Every bit in the source set ends up at least as
> far from the lsb in the target set as it started out. 2) There are no
> combinations of bits that mean things. Each bit is single and
> independent. 3) The "sense" of a bit is never flipped between the
> source set and the target set. 4) We are dealing with exactly 32
> bits.
>
> Some inklings: 1) A loop can be made that runs until there's a
> difference in offset between the source bit and the target bit. 2) A
> loop on the outside of that can be running that figures out that
> offset between the source bit and the target bit. 3) A loop on the
> outside of that can be running that goes through the whole 32 bits.
>
> Just a completely arbitrary example:
>
> Source set:
>
> unsigned long const RED( 1 << 0 );
> unsigned long const GREEN( 1 << 1 );
> unsigned long const BLUE( 1 << 2 );
> unsigned long const CYAN( 1 << 3 );
> unsigned long const MAGENTA( 1 << 5 );
>
> unsigned long const YELLOW( 1 << 8 );
> unsigned long const PURPLE( 1 << 9 );
> unsigned long const ORANGE( 1 << 10 );
> unsigned long const BLACK( 1 << 11 );
> unsigned long const WHITE( 1 << 12 );
> unsigned long const GRAY( 1 << 15 );
>
> Target set:
>
> enum
> {
> red = 0x00000001,
> green = 0x00000002,
> blue = 0x00000004,
> cyan = 0x00000008,
> magenta = 0x00000020,
>
> yellow = 0x00002000,
> purple = 0x00004000,
> orange = 0x00008000,
> black = 0x00010000,
> white = 0x00020000,
> gray = 0x00100000
> };
>
> Resulting expression:
>
> unsigned long translate_bit_set(unsigned long bit_set_in)
> {
> unsigned long bit_set_out = ( (bit_set_in & 0x9f00) << 5) |
> (bit_set_in & 0x2f);
> }
>
> I await the speedy yet maintainable solution.
What about not using templates? The below trades space for speed.
class bit32_to_bit32 {
typedef unsigned long bit32;
typedef unsigned char octet;
typedef unsigned char bitpos;
typedef bit32 table [256];
table the_table [4];
static
void init_table ( table & t ) {
for ( unsigned int i = 0; i < 256; ++i ) {
t[i] = 0;
}
}
public:
bit32_to_bit32 ( void ) {
init_table( the_table[0] );
init_table( the_table[1] );
init_table( the_table[2] );
init_table( the_table[3] );
}
bit32_to_bit32 & add_pair ( bitpos from, bitpos to ) {
unsigned int table_index = 0;
while ( from > 7 ) {
from -= 8;
++ table_index;
}
for ( unsigned int i = 0; i < 256; ++i ) {
if ( ( i >> from ) & 1 ) {
the_table[table_index][i] |= ( 1ul << to );
}
}
return ( *this );
}
bit32 operator() ( bit32 n ) {
octet a = n % 256;
n <<= 8;
octet b = n % 256;
n <<= 8;
octet c = n % 256;
n << 8;
octet d = n;
return ( the_table[0][a]
| the_table[1][b]
| the_table[2][c]
| the_table[3][d] );
}
};
To be used like so:
static
bit32_to_bit32 my_mapping
= bit32_to_bit32()
.add_pair( 0, 29 )
.add_pair( 1, 28 )
.add_pair( 2, 27 );
#include
#include
#include
int main ( void ) {
for ( unsigned long c = 1; c < 32; c <<= 1 ) {
std::cout << std::hex << c
<< " --> "
<< my_mapping(c) << "\n";
}
}
Best
Kai-Uwe Bux
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Why the decision to leave typeinfo::name() out of the standard?
Sebastian Karlsson escribió:
> Hi,
>
> Basically, this little string right here, could be extremely helpful
> if it was portable. Couldn't the standard committee just come up with
> a simple scheme for this? namespace::classname? I'm writing a
> serialization lib and it's damn hard to make it portable without it.
> Does anyone know why it never got to be in the standard?
>
I don't know exactly why, but there is a possible cause:
namespace {
class MyClass {
...
};
}
Now, what should be the name() for this class?
As the way to implement anonymous namespaces is left to the compiler
writer, so name should be.
And think about the enormous quantity of enormous constant strings that
should be stored in the final code if you used some STL or Boost
libraries, with all those templates instantiated with your own templated
classes...
boost::scoped_ptr < Mytemplate
MyFunnyTypeNameObject;
Best regards,
Zara
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Why the decision to leave typeinfo::name() out of the standard?
On Oct 9, 8:12 pm, Sebastian Karlsson
wrote:
> Basically, this little string right here, could be extremely helpful
> if it was portable. Couldn't the standard committee just come up with
> a simple scheme for this? namespace::classname? I'm writing a
> serialization lib and it's damn hard to make it portable without it.
> Does anyone know why it never got to be in the standard?
I don't know, but what do you do about anonymous namespaces?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Compiler allowed to "simplify" floating-point expressions?
On Oct 10, 4:18 am, Marco Manfredini
> Jiang wrote:
> > On Oct 7, 5:59 am, Marco Manfredini
> >> Alan McKenney wrote:
> >> > Does the C++ standard allow a compiler to
> >> > "simplify" floating-point expressions in the way
> >> > we learned in Algebra class?
>
> >> No. The simplification rules of algebra class do not apply here,
> >> because computer floating point arithmetic is (usually) neither
> >> commutative nor associative.
>
> > Maybe this is not the main point for this discussion, but I
> > must say the above statement is not true.
>
> > You did not mention what is the model for the floating point
> > arithmetic, generally speaking, floating point arithmetic for
> > addition and multiplication *are always* commutative.
>
> Unfortunately no. For example the x87 coprocessor architecture (found in
> Pentiums etc.) has 80 bit intermediate results, which means that a
> temporary result which is spilled into memory will lose precision
> against an operand which remains in the FPU. This effectively makes
> commutative ops non-commutative.
>
> Here is a nice writeup which ponders the algebraic properties of
> computer floating point arithmetic:http://zuras.net/FPFallacies.html
>
I do know how you parsed this article, but it clearly shows me that
what I said is correct. It says,
[quote]
Floating-Point Fallacies
[...]
5. Commutative.
Almost all floating-point systems are commutative with respect
to addition. It is easy to arrange for this to be true.
The operands to an add or subtract operation must be compared
anyway to determine which is the greater. That means that the
operation is always effectively done as
the operand order doesn't matter.
Properties of Multiplication.
The situation with respect to multiplication is similar to
that for addition.
[...]
[end quote]
> The rule says that you cannot apply algebraic transformations if the
> underlying types lack certain algebraic properties.
So, what are the "certain algebraic properties" required?
That is the point here. Repeat my words again, without
the detailed specifications on mapping, format, rounding
for floating point, how can the implementors do the
actual check for that rule?
As an extreme example, can we use the properties for
mathematical *real number* for this rule? Or, can we
just use infinite precision arithmetic emulator
for this rule?
> The actual type of
> the operands is completely irrelevant. (Which is btw. the whole point
> of Algebra anyway.) A FP-specification is not necessary:
Then life will be much easier for our poor programmers. :-)
Some properties, especially finite precision and roundoff error,
make floating point arithmetic a totally different beast and
extra attention must be given on them.
Compared with C++, the evolution of floating point support is
more interesting in C language. In C99, floating point is
improved by adding quite a few rules to the language
specification. Some of them are:
1. The limitation for floating point rearrangement.
(quoted by Seungbeom Kim in another post)
2. Floating point arithmetic was specified in Annex F
(normative, 20+ pages), and details for types,
operators, conversions and floating point environment
and optimization. Global and expression transformation
behaviors are specified for optimization.
3. Floating point environment. Rounding, exception
and pragma for floating point are specified.
4. Quite a few new types, functions, macros added.
For example, if we have isnan() in C++ language,
test for NaN will not be a FAQ in clc++m anymore.:-)
Although IEEE 754 is not fully specified, C99 is
considered much floating-point-arithmetic friendly
than C89, and C89's brother, the current C++ language
(I wish I made this point clearer in my previous post).
If 1.9/p15, as you quoted, *is* the right bullet here,
then no above (hard) work needed and everyone,
except the compiler writer, will be very happy. :-)
But this is not the actual picture for the current
situation. For C++ language, there are still lots of
work to be done for this issue.
Go back to the OP's problem, to repeat my points:
1. As a general-purpose programming language, numerical
computation does not have the highest priority and
some issues, especially floating point arithmetic,
are not specified clearly enough.
2. However, implementations involve, slowly but
steady, and we can do the better control for these
issues than before.
vc's fp:precise option (MSDN):
http://preview.tinyurl.com/4uqkwl
gcc's math option, and for OP's association issue:
-fassociative-math:
http://preview.tinyurl.com/6qwxka
3. Unfortunately, compared with other languages suited
to numeric computation or even C99, there are still
lots of work left for us.
Regards,
Jiang
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
On Oct 9, 2:21 pm, joe.foxho...@gmail.com wrote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
stringstream.str() returns a string, not a string reference. It copies
the string and returns it. You're pretty much reassigning a temporary
variable.
The string insertion operator works because thats what it's supposed
to do.
See: http://www.cplusplus.com/reference/iostream/stringstream/
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Compiler allowed to "simplify" floating-point expressions?
On Oct 9, 2:15 pm, Matthias Berndt
> Why?? Who would ever write a program that relies on the fact that ((x +
> y) - y) possibly doesn't equal x? After all, the error cannot be bigger
> than without this optimisation, or can it?
It's easier to sell new computers and compilers if customers can just
recompile their existing code and it 'just works 100%'. It's much
easier to prove that they get exactly the same results (faster/
cheaper) with the new system than that an observed difference does not
represent an increase in error.
- Marsh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
On Oct 10, 3:21 am, joe.foxho...@gmail.com wrote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
>
> Thanks,
> Joe
>
call it like this:
ss.str("have a nice day.").
// str(string) Sets the contents of the buffer to string
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
joe.foxhound@gmail.com ha scritto:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
Because the second line is not doing what you think it does. ss.str()
returns a temporary (empty) string object. You are then assigning "have
a nice day" to that temporary string which is immediately discarded.
Therefore the line has no effect whatsoever.
The fact that operator= is a function (rather than the built-in
operator)allows an rvalue to be present on the left side of the
assignment. This is very surprising and I consider it to be a "defect"
in C++. Fortunately, C++0x provides a syntax to avoid this kind of issues.
If you write the second line correctly, that is:
ss.str("have a nice day.");
you get the result you expect.
HTH,
Ganesh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
catch match
> Try next example with and without a public inheritance:
>
> #include
> #include
>
> class my_exception : public std::exception
> {
> };
>
> int main()
> {
> const my_exception a;
> const std::exception &b( a );
> }
Yes, it fails to compile if inheritance is private.
However this compiles, because conversion is accessible:
class my_exception : std::exception
{
public:
static void foo()
{
const my_exception a;
const std::exception &b( a );
}
};
int main()
{
my_exception::foo();
return 0;
}
It's logical to expect the same conversion rules from catch.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Compiler allowed to "simplify" floating-point expressions?
Alan McKenney wrote:
> Does the C++ standard allow a compiler to
> "simplify" floating-point expressions in the way
> we learned in Algebra class?
The Digital Mars C/C++ compiler does not do the following transformations:
x + 0 â x because not valid if x is -0
x - 0 â x because not valid if x is ±0 and rounding is towards -â
-x â 0 - x because not valid if x is +0
x - x â 0 because not valid if x is NaN or ±â
x - y â -(y - x) because not valid because (1-1=+0) whereas -(1-1)=-0
x * 0 â 0 because not valid if x is NaN or ±â
x / c â x * (1/c) is valid if (1/c) yields an exact result
x != x â false because not valid if x is a NaN
x == x â true because not valid if x is a NaN
x !op y â !(x op y) because not valid if x or y is a NaN
Those transformations are also specifically not allowed in the D
programming language.
-------------
Walter Bright
Digital Mars
http://www.digitalmars.com
Ecmascript, C, C++, D programming language compilers
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
On Oct 9, 12:21 pm, joe.foxho...@gmail.com wrote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
>
> Thanks,
> Joe
Hi Joe,
Try something like this
ss.str("have a nice day!");
that should work for you.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
joe.foxhound@gmail.com wrote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
Actually, I'm surprised this compiles, because it is binding a temporary to
a non-const reference, but I guess that this is because operator= is a
member.
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
The str() function is overloaded, you could use the one taking a string
parameter to set the content. Other than that, you could also pass a string
to the constructor in order to init the content.
Uli
--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
On Oct 10, 4:21 am, joe.foxho...@gmail.com wrote:
> Why won't this work?
>
Because you are doing assignment to an temporary string object
and later doing log using another object.
> stringstream ss;
Here ss's internal state, say stringbuf object's content is empty.
> ss.str() = "have a nice day.";
And now you are doing assignment, but to an temporary object
returned by ss.str(). Think it as:
std::string tmp = ss.str.str();
tmp = "have a nice day";
Note ss.str() returns by value, instead of reference.
> cout << ss.str() << endl;
Since you did not touch the internal state of ss, then
the output should be an empty string. Change the
definition as
stringstream ss("original message");
and see what happens.
HTH,
Jiang
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
joe.foxhound@gmail.com wrote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
No, str() returns a copy of the string. That copy is then modified and
discarded at the end of statement.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
On Oct 9, 12:21 pm, joe.foxho...@gmail.com wrote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
>From an available online STL reference, you can see that there are two
str() functions with the following signatures
string str ( ) const;
void str ( const string & s );
You are calling the no argument one, which returns by value. It's a
"getter". It is not a "setter". You are assigning to a temporary which
is then immediately destroyed: effectively a no-op. You would want to
write:
#include
#include
using namespace std;
int main()
{ stringstream ss;
ss.str("have a nice day.");
cout << ss.str() << endl;
}
or equivalently:
#include
#include
using namespace std;
int main()
{ stringstream ss("have a nice day.");
cout << ss.str() << endl;
}
Why is it done this way? The interface means that you can only get or
set the string at one go. You cannot have a reference to the internal
backing string. I suppose this was done to guarantee the user couldn't
put the stringstream in a inconsistent state. (I still wish you could
at least swap the internal backing string instead of making a copy,
but that's probably a discussion for another time.)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Compiler allowed to "simplify" floating-point expressions?
On Oct 10, 4:59 am, Gabriel Dos Reis
> Alan McKenney
>
[...]
> |
> | I ask because I was at one time told that the
> | C standard explicitly allowed such algebraic
> | transformations, even though it changes the
> | meaning of the code.
>
> I'm having hard time finding that anywhere in the C standard.
>
I parsed it as, C++/C allow algebraic transformations under some rules
[but not quite applicable for floating point arithmetics, IMHO ], and
"changes the meaning of the code" is the possible consequence.
Of course this is maybe not the intention of the languages.
> There are well known algorithms (based on the IEEE 754 semantics) that
> would break if the compiler started playing ill-advised games without
> being invited to do so.
Yes, implementations do not respect user specified group/order
are useless for floating point computation.
Regards,
Jiang
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
On 2008-10-09 21:21, joe.foxhound@gmail.com wrote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
str() returns a value, not a reference. In other words what you get is a
copy of the buffer used by the stringstream. So your assignment only
changes this copy, not the buffer of the stringstream.
--
Erik Wikström
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Compiler allowed to "simplify" floating-point expressions?
Matthias Berndt
| > But a compiler that assumes that adding 1.0 and
| > then subtracting it again will result in the
| > original value, and optimizes code on that
| > assumption, is almost useless for serious
| > (floating-point) numerical work.
| Why?? Who would ever write a program that relies on the fact that ((x +
| y) - y) possibly doesn't equal x?
To compute the error that arises when computing x + y as floating
point number. Again, See the algorithms of Dekker, Kahan, Knuth, etc.
| After all, the error cannot be bigger
| than without this optimisation, or can it?
But what if he is interested precisely in the error?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
catch match
On 9 Okt, 21:59, anon
> gute...@gmail.com wrote:
> > Thanks to everyone who replied.
>
> > Geert-Jan Giezeman, anon and Jiang, looks like you are correct.
> > 15.3/3 literary says: unambiguous *public* base class
>
> > However, the code outputs 1 on MSVC. It outputs 2 when foo is made non-
> > member and not friend of my_exception. So, a catch is a match in MSVC
> > when the conversion is accessible, regardless to inheritance kind.
>
> Obviously a bug in the MSVC
Or it was their opinion that this special case was overlooked by
15.3/3, and that this was the intended behavior.
> > Also anon wrote "accessible base class".
> > I think it is intuitive to expect matching based on accessiblity, like
> > with static_cast and implicit conversion.
>
> > So here's another question:
> > Is it a problem in standard, or word "public" was put there on purpose ?
> > The same question applies to dynamic_cast at 5.2.7/8.
>
> I am not quite following you.
>
> Try next example with and without a public inheritance:
>
> #include
> #include
>
> class my_exception : public std::exception
> {
>
> };
>
> int main()
> {
> const my_exception a;
> const std::exception &b( a );
>
> }
>
> If you don't get the error, change the compiler (or better yet, change
> the os)
>
Agreed, but this example has little to do with the catch problem.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Compiler allowed to "simplify" floating-point expressions?
On Oct 8, 2:29 pm, Artie Choke
> On Oct 7, 8:22 pm, Greg Herlihy
> > On Oct 5, 2:24 pm, Alan McKenney
> > > double x;
> > > ....
> > > if ( ( x + 1.0 ) - 1.0 )
> > > as
> > > double x;
> > > ....
> > > if ( x )
>
> > Yes. Adding and subtracting an exactly-represented constant value
> > (such as 1.0) has the same net result as adding 0.0.
>
> No. Not in floating-point. If x is less than
> std::numeric_limits
> effect, and the result of the subtraction will (should) be 0.0, not x.
If x is less than std::numeric_limits
value is already 0.0 - and the "if (x)" expression will evaluate to
false. So adding and subtracting 1.0 to x will have no net effect on
x's value, and the if expression will still yield "false".
Greg
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
stringstream misunderstanding
The str() method with no args is const so you can't change the
object's class member. You can call str(arg) and pass in a new string
object:
#include
#include
using std::cout;
using std::endl;
int main() {
std::stringstream ss;
cout << "before: " << ss.str() << endl;
ss.str("my string");
cout << "after: " << ss.str() << endl;
return 0;
}
Also, see http://www.cplusplus.com/reference/iostream/stringstream/
On Oct 9, 1:21 pm, joe.foxho...@gmail.corote:
> Why won't this work?
>
> stringstream ss;
> ss.str() = "have a nice day.";
> cout << ss.str() << endl;
>
> I know that
> ss << "have a nice day.";
> works, but I thought the str() function would permit me to read to
> write to the ss buffer.
>
> Thanks,
> Joe
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
operator << for ostringstream returning ostream is unintuitive
Is it not a reasonable user assumtion that the return type of <<
should be the same the type as its first argument? (So that any
operation that is valid for the first argument should also be valid
for the return type, to allow intuitive chaining)
However, for ostringstream the return type of operator << is the base
type ostream rather than ostringstream itself (because ostringstream
does not provide any << overload of its own). As a ostringstream user
I find this to be inconvenient and bit surprising. Am I being
unreasonable?
#include
void libFunc(std::ostringstream& msg);
int main(void) {
libFunc( std::ostringstream() << "Test" << 1); // Error
(std::ostringstream() << "Test" << 2).str(); //Error
//need to be more verbose to get it to work.
std::ostringstream namedsstr1;
namedsstr1 << "Test" << 1;
libFunc( namedsstr1 ); // OK
std::ostringstream namedsstr2;
namedsstr1 << "Test" << 2;
namedsstr2.str(); //OK
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Announce: just::thread C++0x thread library beta v0.3
Mathias Gaunard
> On 12 nov, 14:06, JoshuaMaur...@gmail.com wrote:
>> On Nov 11, 10:57 pm, Mathias Gaunard
>>
>> > Why not make a portable one?
>> > I'm sure boost would be interested.
>>
>> I don't think you can. You'd have to have a separate implementation
>> for each platform.
>
> I actually meant multi-platform.
> But still, it is perfectly possible to implement non-preemptive
> threading in standard C++. Does std::thread mandate preemptiveness?
That's a tricky one. I'm not sure the words require it, but I believe
it needs to be pre-emptive in practice, otherwise things like waits
would not work: if you're waiting on a condition variable, you don't
know which thread will signal it. If the implementation switches to a
thread that doesn't then call any library calls that can yield to the
scheduler (it's calculating the first million digits of pi into a
pre-allocated buffer, for example) the waiting thread is now blocked
unless the scheduler pre-empts the long-running thread.
Anthony
--
Anthony Williams
Author of C++ Concurrency in Action | http://www.manning.com/williams
Custom Software Development | http://www.justsoftwaresolutions.co.uk
Just Software Solutions Ltd, Registered in England, Company Number 5478976.
Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Test a string for Integer
Jack Klein ha scritto:
> On Sat, 15 Nov 2008 11:42:53 CST, Alberto Ganesh Barbati
>
>
>> // assuming buf is null-terminated
>> char* endptr;
>> long i = strtol(buf, &endptr, 10);
>> if (*endptr)
>> {
>> // buf contains a string
>
> Or a string representing an integer value followed by more characters
> not part of that integer value representation. If the buffer
> contained "3.14159", i would be equal to 3 and endptr would point to
> the '.'. Or, since in the OP's case, he used fgets(), it might well
> point to the '\n' that terminated the input line.
Correct. Anything that isn't an integer is treated as a string. That's
exactly what (I believe) the OP asked. In particular, 3.14159 is not an
integer so it shouldn't be parsed as such (and it doesn't with this code).
>
>> }
>> else
>> {
>> // buf contains an integer and the value is i
>
> Or the first character in buf was a '\0'.
>
Correct. I assumed that the input string is non-empty. That's usually a
safe assumption because reading an empty string is usually flagged as an
error before trying to parse the string. However, thanks for pointing
that out.
Ganesh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Variadic templates
Boris Rasin ha scritto:
> On Nov 14, 6:09 pm, Mathias Gaunard
>> On 14 nov, 00:31, Boris Rasin
>>
>>> template
>>> class store
>>> {
>>> public:
>>> store (Args ... args) : members (args) ... {}
>>> void forward() { some_func (members ...); }
>>> Args ... members; // Error: template parameter pack expansion not
>>> supported in this context. Why not?
>> What could it do?
>> Try tuple
>
> Like I said, I want (perfect) forwarding at a later stage (see
> "forward" member function in my sample). And "tuple
> wouldn't work.
>
All you need is an helper function like this:
template
/* whatever */ invoke(T f, tuple
which calls f with the supplied arguments. It should not be too
difficult to make it a perfect forwarder.
Ganesh
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
working draft N2768: non-unique addresses
On Nov 16, 9:53 am, "wolf.lammen"
> The current working draft N2768, in 29.2 paragraph 3, speaks of
> mapping the same memory to different address spaces.
> On the other hand, this is explicitly forbidden by 1.7 paragraph 1,
> because each memory byte must have a unique address.
A byte of shared memory does have a unique address (that is, an
address that it shares with no other byte of memory). The only
difference between a shared and unshared memory location is that is
that the former might have more than one unique address (in fact, one
unique address for each process that is sharing the memory). And there
is nothing in §1.7 or anywhere else limit a byte of memory in C++
s memory model to no more than one, unique address.
> Does anybody know how to resolve this conflict? Is multiple mapping
> allowed or not?
There is no conflict. Whether shared or not, each memory location
accessible to a C++ program is uniquely addressable.
Greg
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Tail padding in base classes vs. tail padding in class members.
On Nov 29, 8:28 pm, Boris Rasin
> > class B : public A { int foo; };
>
> > This class also ends up having size of 16 bytes, since 'foo' gets
> > packed into the tail padding of the base class A. Everything fine,
> > just as anybody would want.
>
> I am not sure this is what I'd want. Consider:
>
> B b;
> A* pa = &b;
> A a;
> memcpy (pa, &a, sizeof (A));
>
> This is legal C++98 ([basic.types]/3) and yet it will override value
> of "foo" if it is indeed packed as you say it is.
Your example is not legal C++98. A is not a POD (not aggregate
because non-public data members). As the OP has discovered, if A is
declared as struct A {...} it becomes POD, and memcpy becomes legal,
and the optimization is not allowed.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Variadic templates
On Nov 30, 5:29 pm, Boris Rasin
> On Nov 30, 10:57 am, Daniel Krügler
> wrote:
>
> > Maybe the introduction of variadic members opens up a can of worms ;-)
>
> Perhaps I am missing something obvious, but to me the following two
> expansion cases seem extremely similar, even if not identical:
>
> template
> struct store
> {
> store (Args ... args); // Case 1, allowed by current draft
> Args ... members; // Case 2, NOT allowed by current draft
>
> };
>
FYI: if your proposal is accepted (i.e. to allow member template
packs) then look how much simpler and more intuitive the definition of
tuple also becomes - (specifically it doesn't try and emulate tuple-
like behavior while being implemented in terms of a recursive list-
like structure).
template
{
Args ... args;
tuple(add_const_reference
template
tuple(const tuple
template
tuple& operator=(const tuple
{
args = other.args...; // grammar allowed currently by 14.5.3/4 -
use , as a separator
return this;
}
};
template
bool operator==(const tuple
{
return true && (t1.args == t2.args) ...; // also currently allowed -
use && as separator
}
template
bool operator<(const tuple
{
return true && (t.args < u.args) ...;
}
tuple
You can also have tuple aggregates:
template
{
Args ... args;
};
tuple_aggregate
take place
And if the above equality and comparable operators were written using
template template parameters - then we could compare tuple aggregates
too.
As regards concepts - they should not be impacted since we can not
specify data member requirements.
Anyway - Like you, I think there are compelling reasons to allow
member template packs - and we should really try and put a DR or
Proposal together asap.
Even if it doesn't get accepted for C++09 - perhaps it can make it
into the next TR.
regards,
Faisal Vali
Radiation Oncology
Loyola
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Exception specifications unfortunate, and what about their future?
Thomas Beckmann wrote:
>>> Java has a garbage collector so there are no dtors; C++ has RAII so
>>> there are no finally statements. These are competing concepts.
>>
>> Non sequitur. Garbage collectors take care of memory, but destructors
>> have much wider responsibilities. Hence the presence of a garbage
>> collector does not eliminate the need for destructors.
>
> Absolutely correct, I did not say otherwise,
> 1. Garbage collection does not eliminate the need for resource management,
> i.e. Dispose Pattern of C#, Close methods in Java,... This is since GCs
> reclaim memory only (Maybe a limitation of current technology?)
> 2. Destructors need to be executed deterministically by design, thus they
> can not be supported in a garbage collecting environement, i.e. C#/Java
have
> finalizers and no dtors.
>
> A dtor must run exactly at the end of the scope to be of use. As a result
> supporting dtors eliminates the need for a GC as the dtor "knows" exactly
> when to reclaim memory. Approximating this sequence point is the mission
of
> GC algorithms. In conclusion, garbage collection implies dtors are not
> supported, since a GC does not run deterministically. Finally is a work
> around for this lack of dtors. In all cases a finally clause can be
> transformed into a dtor unless you have no dtors in the runtime, thats why
I
> meant C++ doesn't need no finallies.
>
> In summary,
> if there is a GC you have no dtors, and
> if you have dtors you need no finallies...
Once again, this doesn't follow. You can plug the Boehm collector into
C++ and yet have destructors. What you cannot have is deterministic
destruction for garbage collected *objects*, since, by design, garbage
collection is non-deterministic from the perspective of the collector's
user. However, the presence of a garbage collector does not mean all
objects have to be garbage collected. This is only the case with Java,
the designers of which decided to do away with automatic objects. In
principle, there is no technical reasaon against garbage-collected and
automatic objects existing side-by-side.
--
Gerhard Menzl
Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Exception specifications unfortunate, and what about their future?
Brendan wrote:
>> Richard Corden wrote:
>> Which would make the container unusable with types from third-party
>> libraries that don't have their exception hierarchy rooted in
>> std::exception,
>
> This is a non-argument. Containers are only compatible with types
> designed to be compatible with them, that goes without saying. The
> standard containers don't work with many types, including those
> without copy constructors, those without relational operators (you
> can't just stick a pointer in a map), etc. You only need an adapter if
> you want incompatible types to work together.
This is a flawed argument. Standard containers require copyability and
assignability because these operations are necessary to implement the
containers. But a standard container has no business whatsoever with
specific exceptions an item type may throw. All that is required is that
the container propagate the exception outward. Without exception
sepcifications, this is guaranteed by the language.
Think about what "an adapter [to make] incompatible types [...] work
together" would mean in the context of statically checked exception
specifications. Since it would be impossible for a standard container to
specify any exceptions other than standard exceptions, an adapter for a
container item would have to convert all user-specific exceptions to
stdandard exceptions, thereby preventing all non-standard information
from reaching higher-level code.
A major design goal of exceptions is the transparent handling of errors
across long calling distances without making intermediate code dependent
on the details. Statically checked exception specifications thwart this
purpose. It just doesn't scale, and it is incompatible with generic
programming.
--
Gerhard Menzl
Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
partial specialization of a single class member, without specializing the rest of the class?
On Dec 1, 1:25 am, "Jonathan Thornburg [remove -animal to reply]"
> Sorry to followup on my own posting, but I've found an "other means",
> i.e. a workaround. It's not pretty, but it does seem to work.
>
> Just to recall the context, I have 4 policy classes A, B, X, and Y,
> and a template class P with two template parameters, AB and XY. All
> 4 combinations P, P, P, and P are valid. P has
> a member function P::foo() which I can implement with generic code.
> However, it also has a member function P::bar() whose implementation
> requires separate code paths for XY=X and XY=Y. (In my real application
> these code paths must be separate at compile time, as the XY=Y code
> uses Y members which don't exist in X.) The problem is how to implement
> partial specialization of P::bar() for XY=X and XY=Y without also having
> to duplicate P::foo(). In my previous posting I gave what seems to me
> to be the obvious code; g++ says that code is illegal.
>
> Here's my workaround:
...
> // forward declarations
> template
> template
> template
> template
self);
>
> // partial specialization of non-class functions isn't allowed,
> // so we define a fully specialized bar_forwarder()
> // for each of the 4 possible combinations of the AB and XY template
args
> template <>
> inline void bar_forwarder(P& self) { bar_X_doit(self);
}
> template <>
> inline void bar_forwarder(P& self) { bar_X_doit(self);
}
> template <>
> inline void bar_forwarder(P& self) { bar_Y_doit(self);
}
> template <>
> inline void bar_forwarder(P& self) { bar_Y_doit(self);
}
...
> // the actual partially-specialized code for P
> template
> void bar_X_doit(P
> {
> // code which assumes class X, but still handles AB = either A or B
> // ... 'self' is needed here to access things like self.foo()
> }
>
> // the actual partially-specialized code for P
> template
> void bar_Y_doit(P
> {
> // code which assumes class Y, but still handles AB = either A or B
> // ... 'self' is needed here to access things like self.foo()
> }
If you use a helper class instead of helper functions you can use
partial specialisation, avoiding the need for the extra forwarding
function.
template
template
struct bar_impl
static void apply(P
{
// code which assumes class X, but still handles AB = either A or
B
// ... 'self' is needed here to access things like self.foo()
}
};
template
struct bar_impl
static void apply(P
{
// code which assumes class Y, but still handles AB = either A or
B
// ... 'self' is needed here to access things like self.foo()
}
};
template
struct P
{
void bar() { bar_impl
friend struct bar_impl
};
Which is not much more than the original specialisation would be (if
it were legal).
> // explicit template instantiations
> template class P;
> template class P;
> template class P;
> template class P;
I presume these were to test the solution, because they're not needed
for it to work.
> While this solution works, IMHO it's seriously inelegant. Can anyone
> suggest a cleaner way to partially specialize a member function of a
> class template, without having to duplicate all the rest of the class?
template
struct P_impl
{
// Put the full implementation of P here, except for bar.
// Any members needed by bar should be protected.
}
template
struct P;
template
struct P
void bar()
{
// code which assumes class X, but still handles AB = either A or
B
}
};
template
struct P
void bar()
{
// code which assumes class Y, but still handles AB = either A or
B
}
};
You'll have difficulty doing this if the rest of P needs to call bar.
(It can be done with downcasting.)
Yechezkel Mett
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Template parameter matching for class and class method
On 1 Dez., 20:04, Faisal Vali
> On Nov 30, 6:16 pm, Mathias Gaunard
>
> > On 30 nov, 09:58, Faisal Vali
>
> > > struct S { void bar(); char foo(S); char* (*foobar(int,char,double))
> > > ();};
> > > S s;
>
> > > auto m1 = makeMethod(&S::bar, s);
> > > auto m2 = makeMethod(&S::foo, s, S());
> > > auto m3 = makeMethod(&S::foobar, s, 0, '0', 0.0 );
>
> > Isn't that just std::bind?
>
> The difference maybe minor depending on how strongly you feel about
> storing the member pointer as a non-type template parameter (as the OP
> was trying to do - and which is not possible with C++03 & bind). But
> like i said, one can come close in C++03.
>
> Either way, it is interesting to note that boost::bind requires
> 500-1000 lines of code to implement (if not more) what we can do in C+
> +0x in < 25 lines.
I think you provided a really nice solution to the OP's
problem and I guess the overhead of your implementation
is remarkably small. What I sometimes wish for C++XX is
a syntax, which prevents the redundancy to provide the
class name as part of the function pointer specification
and the additionally provided object. Delphi allows the
following construct (freely translated into C++) to
store a closure:
auto m1 = s.bar; // Deduces type of s and binds the
// pair of s and &Type::bar
This syntax does not support parameter binding, but it's
lack of is one of the annoying things in C++ IMO.
Greetings from Bremen,
Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Mapping one set of bits to another
On Dec 1, 1:16 am, Rick
> I added a piece to go from the particular bits, that the libraries
> supply, to the bit offsets, that we need.
>
> template
> enum { val = Offset<(n>>1)>::val + 1 };
>
> };
>
> template<> struct Offset<1> {
> enum { val = 0 };
>
> };
Nice addition. Maybe you should ensure that your n argument has just 1
bit set, that is what your code expects:
template
struct Offset {
static_assert(N > 0 && (N & 1) == 0);
enum { value = Offset<(N >> 1)>::value + 1 };
};
template <>
struct Offset<1> {
enum { value = 0 };
};
static_assert is in C++09, or in boost or a TMP exercise for the
reader ;-)
VC++ with /Ox also gets it optimized to the minimal implementation,
like Sun CC. I'm surprised that g++ cannot optimize it further. You
could help the optimizer a bit by specializing BitMapping further for
these cases: From < To, From == To and From > To. This does complicate
your code at little extra gain though.
> So we've gone through the following versions of this routine:
> 1. Speedy, but if one of the two libraries changes its representation,
> it'll break.
> 2. Robust, but too slow for the application. I didn't exhibit this
> one. It just iterates through the bits, and applies a table of
> desired destinations.
> 3. Speedy and robust, what metaprogramming is for!
Indeed, great that it works for you too!
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
A problem with "extern"
On Nov 30, 5:29 pm, drop
> I have write a short program that use a static globle variabl .That
> variable has been modefied in another file, but the result is not as
> expect,nothing to output to show that variable has been modefied!
When a global variable is made static, it means that the variable has
internal linkage. This means that the variable is available only in
the translation unit in which it is occurring. Each translation unit
will have its own copy. To understand this better, consider the
following example (and note that each translation unit has its own
copy):
$ cat trans.h
#include
#define ADDRESS(x) std::cout << &x << std::endl;
static int i;
extern void trans1();
extern void trans2();
$ cat trans1.cc
#include "trans.h"
void trans1() {
ADDRESS(i)
}
int main() {
trans1();
trans2();
}
$ cat trans2.cc
#include "trans.h"
void trans2() {
ADDRESS(i)
}
$ make
g++ -c -o trans1.o trans1.cc
g++ -c -o trans2.o trans2.cc
g++ -o trans trans1.o trans2.o
$ ./trans
0x446020
0x446040
$ uname -a
CYGWIN_NT-5.0 IL0015agurusam1 1.5.25(0.156/4/2) 2008-06-12 19:34 i686
Cygwin
$ g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
$
HTHs.
Rgds,
anna
--
http://missingrainbow.blogspot.com
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
A problem with "extern"
drop schrieb:
> I have write a short program that use a static globle variabl .That
> variable has been modefied in another file, but the result is not as
> expect,nothing to output to show that variable has been modefied!
"global" is actually not a term that is defined in C or C++. You
probably want the variable have external linkage such that translation
units not defining it can access it. "static" and "external linkage"
contradicts each other; "static" means that the variable is only visible
in the current translation unit, "extern" means that it is declared in
the translation unit, but not necessarily defined there.
> /////////////// "main.h" ///////////
> #ifndef MAIN_H
> #define MAIN_H
>
> #include
>
> static std::vector
This creates one instance of data for each translation unit including
this file, and a variable that is only visible within the translation
unit. Hence, each translation unit including main.h gets its own
instance of data. However, what you want to have here is a declaration
of the data such that each translation unit including this file becomes
aware of the data.
extern std::vector
>
> void init();
>
> #endif
>
> //////////////// "main.c" ////////////////
> #include "main.h"
> #include
> #include
>
> using namespace std;
> extern std::vector
This is just a declaration, but data is already declared in main.h, so
this does nothing here. Instead, you should *define* data exactly once,
so probably here. Thus:
std::vector
It is then not "static" but as said, static and global contradicts each
other. The variable should exist once throughout the program, so it
cannot be static. It must have external linkage, and must be defined in
one of the translation units; this is what "extern" does.
> #include "main.h"
> #include
>
> extern std::vector
This includes already main.h where data is declared. You don't need to
declare it twice. Just remove this line.
> why???
Because you're confusing what static and extern actually mean. (-;
So long,
Thomas
P.S.: As a naming convention, I suggest to name C++ source files with
the .cpp extender, and C++ header files with the .hpp extender. Some
compilers decide on the extender whether to compile the code as C or as
C++ source, and .c and .h often indicate C and not C++.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Variadic templates
On 1 Dez., 00:29, Boris Rasin
> On Nov 30, 10:57 am, Daniel Krügler
> wrote:
>
> > Maybe the introduction of variadic members opens up a can of worms ;-)
>
> Perhaps I am missing something obvious, but to me the following two
> expansion cases seem extremely similar, even if not identical:
>
> template
> struct store
> {
> store (Args ... args); // Case 1, allowed by current draft
> Args ... members; // Case 2, NOT allowed by current draft
>
> };
>
> In both cases compiler generates individual variables and in both
> cases there is no syntax
> to access them individually (your suggestion for array like individual
> access syntax
> would have to be applied in both cases and is a separate issue).
>
> What are the semantical or implementation differences which led to
> acceptance
> of case 1 into the draft but not the case 2?
The key difference is that in (1) there are no variadic names with
linkage (as of 3.5 [basic.link]) that could be named out of the scope
of the varidic member function declaration. This is so, because
function parameters and other variables of local scope cannot be
named outside their scope.
But in (2) the variadic member pack "members" would have linkage.
It's easy to see that in Larry Evans' example where we have to find
a way to "name" individual members. Now consider that we would
(arbitrarily) decide that the member names would be chosen to be
member1, member2, etc. This would cause a naming conflict in
examples like these:
template
struct store
{
int members1;
Args ... members;
};
This problem would only occur if the pack has at least a size
of 1 and the error is far from easy to understand. Therefore
my suggestion to forbid explicit access to individual names
of such a pack (The array-like notation would be one way
to realize that).
My - not yet confirmed - assumption is that implementors
could solve the linkage name problem (that is the way how they
uniquely assign their internal linkage names) for these entities,
but we still need to invent new syntax to allow programmers to
'name' the pack members once they have instantiated such an
entity as explained above. The same naming problem occurs
in the double_all example that I provided (but that is not a
different one from your proposed variadic members. If the first
one is solved, the second one is easily provided).
Greetings from Bremen,
Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Odd feeling about constexpr and recursion.
On 1 déc, 00:27, Rodrigo
> As far as I know, constexpr functions are now allowed to be called
> recursively:
>
> constexpr int fibonacci(int n)
> {
> return ((n < 2)? n : fibonacci(n - 1) + fibonacci(n - 2));
>
> }
>
> int main( )
> {
> std::cout << fibonacci(250) << '\n';
>
> }
>
> This will probably take a bit to compile but not too much since its
> expected that the compiler applies memoization. However, this version
> of the same program:
>
> constexpr int fibonacci(int n)
> {
> return ((n < 2)? n : fibonacci(n - 1) + fibonacci(n - 2));
>
> }
>
> int main( )
> {
> int n;
>
> std::cin >> n;
> std::cout << fibonacci(n) << '\n';
>
> }
>
> with 250 as its input will take forever.
That function certainly always ends (assuming enough memory for the
stack). Did you mean "a long time" instead of forever?
Would you like the runtime version to use memoization too, to keep the
same complexity as the compile-time one?
> - Prohibit recursion on constexpr again. I'm not sure if this could do
> more harm than good, but its obvious that the current constexpr (as I
> understand it) has a problem if recursion is allowed.
I suppose it is expected, just like for templates, that the compiler
sets a recursivity limit.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
A problem with "extern"
On Dec 1, 4:29 am, drop
> I have write a short program that use a static globle variabl .That
> variable has been modefied in another file, but the result is not as
> expect,nothing to output to show that variable has been modefied!
> /////////////// "main.h" ///////////
> #ifndef MAIN_H
> #define MAIN_H
>
> #include
>
> static std::vector
>
> void init();
>
> #endif
>
> //////////////// "main.c" ////////////////
> #include "main.h"
> #include
> #include
>
> using namespace std;
> extern std::vector
> int main()
> {
>
> init();
> vector
> while(it != data.end ())
> {
> cout << (*it) << endl;
> ++it;
> }
> return 0;
>
> }
>
> ////////////////////// "init.cpp" ////
> #include "main.h"
> #include
>
> extern std::vector
>
> void init()
> {
> data.push_back (1);
> data.push_back (2);
> data.push_back (3);}
>
> ////////////////////
> why???
Hi,
The static global variable cant be modified in another file. This
variable can only be used in the file where it is declared. If you
want to access it in another file, you may need to go for non-static
version of global variable.
The static variables having namespace scope have internal linkage. The
entity it denotes can be referred to by names from other scopes in the
same translation unit only.
Regards,
Boopathi D.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Rationale of non-const reference to temporaries
Hello,
I would like to submit the following code to your attention:
#include
#include
void f(std::string& s)
{ std::cout << s << std::endl; }
int main(int argc, char* argv[])
{
std::string s("Hello world");
f(s); // <- This is ok
f(std::string("Hello world")); // <- This is incorrect (g++)
return 0;
}
It compiles without errors on VC++ 8.0 (2005), while on gcc 4.1.2
(and later) it gives the following error:
g++ -O2 -g -Wall -fmessage-length=0 -c -o main.o main.cpp
main.cpp: In function 'int main(int, char**)':
main.cpp:11: error: invalid initialization of non-const reference of
type 'std::string&' from a temporary of type 'std::string'
main.cpp:4: error: in passing argument 1 of 'void f(std::string&)'
make: *** [main.o] Error 1
What I know is that temporaries can be passed as const references
and that VC allows passing them as non-const references as an
extension to the standard.
What I don't know precisely is whether there is any potential risk
of error in doing as above.
Could you help me understand the rationale of the two approaches?
Thanks in advance,
eca
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]