The following code fails to compile with g++ (GCC) 4.7.0 20110809 (experimental) [trunk revision 177606] template <typename From, typename To> class implicit { private: static From from_type(); static char selector(To); static char (&selector(...))[2]; public: static const bool value = sizeof(selector(implicit::from_type())) == 1; }; template <typename From, typename To> const bool implicit<From, To>::value; class abstract { virtual void pure() = 0; abstract(const abstract&); }; int main() { return implicit<const abstract&, long long int>::value; } # Note that I am not using C++0x. g++ -c implicit.cc implicit.cc: In instantiation of 'const bool implicit<const abstract&, long long int>::value': implicit.cc:20:54: required from here implicit.cc:16:3: error: 'abstract::abstract(const abstract&)' is private implicit.cc:8:72: error: within this context implicit.cc:8:72: error: cannot allocate an object of abstract type 'abstract' implicit.cc:14:7: note: because the following virtual functions are pure within 'abstract': implicit.cc:15:16: note: virtual void abstract::pure()
In this testcase, you're calling selector with an 'abstract' argument. 5.2.2/7 says, The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression. 4.1/2 says, When an lvalue-to-rvalue conversion occurs in an unevaluated operand or a subexpression thereof (Clause 5) the value contained in the referenced object is not accessed. Otherwise, if the glvalue has a class type, the conversion copy-initializes a temporary of type T from the glvalue and the result of the conversion is a prvalue for the temporary. Hmm, having different semantics for lvalue-rvalue conversion depending on whether the expression is evaluated is surprising, but that does seem to be what the standard says. Alrighty then.
Author: jason Date: Fri Aug 12 21:27:52 2011 New Revision: 177722 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=177722 Log: PR c++/50034 * call.c (convert_arg_to_ellipsis): force_rvalue only in potentially evaluated context. Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/cpp0x/defaulted28.C
Fixed.