////////////////////////////////////////
#include <cassert>
void Inc(const int& input, int& output)
{
output = input + 1;
assert( output == (input + 1) );
}
int main(int argc, char**)
{
Inc( static_cast<int>(argc), argc );
}
////////////////////////////////////////
I tried both GCC 4.3.2 and MSVC 9. On MSVC, the static_cast<int> doesn't have
any effect (because argc is an int already), so the input and the output
argument refer to the very same object. Causing the assert to fail. While
GCC doesn't get me the assert failure, so apparently GCC has the input
argument referring to a temporary copy of argc. Is the static_cast<int>
indeed supposed to create a temporary copy?
Kind regards,
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
From the C++ draft standard (n2798.pdf page 98 Section 5.2.9p1)
"The result of the expression static_cast<T>(v) is the result of
converting the expression v to type T. If T is an lvalue reference
type, the result is an lvalue; otherwise, the result is an rvalue. The
static_cast operator shall not cast away constness."
Since in your code T is not an lvalue reference type, the result is an
rvalue. And so a temporary object is created. To avoid temporary
object you can cast to reference type as follows:
RL1 1017 $ cat cast.cc
#include <iostream>
#include <cassert>
struct T {
T() { std::cout << "T()" << std::endl; }
T(const T&) { std::cout << "T(const T&)" << std::endl; }
};
void Inc(const T& input, T& output) {
if ( &input == &output )
std::cout << "No temporary obj created." << std::endl;
else
std::cout << "Temporary obj created." << std::endl;
}
int main() {
T obj;
Inc( static_cast<T&>(obj), obj );
Inc( static_cast<T>(obj), obj );
}
RL1 1018 $ g++ -Wall -Wall -O3 -pedantic cast.cc
RL1 1019 $ ./a.out
T()
No temporary obj created.
T(const T&)
Temporary obj created.
RL1 1020 $ g++ --version
g++ (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52)
Copyright (C) 2006 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.
RL1 1021 $
Rgds,
anna
--
Used Car For Sale ($2800/-) 1998 Ford Explorer XLT (Mileage 189000)
Naperville, IL 60563, USA. Will sell by 2nd or 3rd week of Dec 2008.
5.2.9/1:
| The result of the expression static_cast<T>(v) is the result of
| converting the expression v to type T. If T is a reference type,
| the result is an lvalue; otherwise, the result is an rvalue.
| Types shall not be defined in a static_cast. The static_cast
| operator shall not cast away constness (5.2.11)."
Here it says the result is an rvalue for static_cast<int>. Furthermore,
5.2.9/2:
| An expression e can be explicitly converted to a type T using a
| static_cast of the form static_cast<T>(e) if the declaration “T t(e);”
| is well-formed, for some invented temporary variable t (8.5).
| The effect of such an explicit conversion is the same as performing
| the declaration and initialization and then using the temporary
| variable as the result of the conversion. The result is an lvalue
| if T is a reference type (8.3.2), and an rvalue otherwise. The
| expression e is used as an lvalue if and only if the initialization
| uses it as an lvalue.
Here it says explicitly that a temporary variable is created and used.
--
Seungbeom Kim
Thank you, Seungbeom! Also thanks, anna! I just realized I should have
disabled the Microsoft-specific language extensions ("/Za"), when I did
the MSVC compilation.
MSVC *does* create a temporary variable when doing static_cast<int>,
when its language extensions are disabled.
Kind regards, Niels
--
I'm interested in what results you get for similar constructs, which a
compiler might also be tempted to meddle with:
Inc( +argc, argc );
Inc( argc+0, argc );
--
Nice suggestion! For both +argc and argc+0, MSVC 9 (SP1) appears to create
a
temporary (I don't get assert failures on those two), even when
Microsoft-specific language extensions are enabled.
Kind regards, Niels
Your struct T and my Inc function have made it into a compiler bug
report :-) Apparently the CodeGear C++ compiler doesn't always create
a temporary when it should, as reported by Fraser Ross: Report #69102 -
"static_cast a type to the same type"
http://qc.codegear.com/wc/qcmain.aspx?d=69102
Kind regards, Niels
--