This link explains very clearly why VC++ creates a temporary to initialize the local reference, complete with a decision graph, and it seems that the Rcpp expression template code should lead to the "create temporary" branch: http://msdn.microsoft.com/en-us/library/szywdw8k.aspx
These comments come from an IBM site explaining when references are directly bound when initialized (no temporary): Direct Binding Suppose a reference r of type T is initialized by an expression e of type U. The reference r is bound directly to e if the following statements are true: - Expression e is an lvalue - T is the same type as U, or T is a base class of U - T has the same, or more, const or volatile qualifiers than U The reference r is also bound directly to e if e can be implicitly converted to a type such that the previous list of statements is true. Dominick On Tue, Jan 18, 2011 at 4:46 PM, Dominick Samperi <djsamp...@gmail.com>wrote: > Opps, I was too quick to declare victory here. That warning about > temporary reference initialization is not innocuous: crashes still > occur under VC++ (even with the updated RcppCommon.h) but > it is difficult to predict when they will occur. The Extractor.h > work-around fixes the problem for now. > > The question that remains unanswered is: is this a quirk of > VC++ or is the warning something that applies more generally? > > Dominick > > > On Tue, Jan 18, 2011 at 4:18 PM, Dominick Samperi <djsamp...@gmail.com>wrote: > >> To finish up this thread, it turns out that the VC++ problems did >> help to reveal an architecture-dependent behavior of Rprintf >> (under GCC) that >> developers probably should be aware of, and it also points to >> a potential problem with the way temporary references are >> initialized in the expression template code. >> >> On the other hand, the non-Rprintf related problems seem to >> be due to the fact that I did not update RcppCommon.h in >> my VC++ builds. After updating RcppCommon.h (and adding >> VC++ to the list of supported compilers), the expression >> template code works fine. I still get the warnings about the >> initialization of reference temporaries though. >> >> On Rprintf, it is safest to not use format controls like >> "%lf" and "%Lf". Use "%f" instead. Since I have programmed >> in C/C++ for a long time I was in the habit of using "%lf", >> but the "l" qualifier has since been redefined to apply to >> ints (and long ints) only, and "%Lf" is intended for use >> with 'long double' type. >> >> Dominick >> >> >> On Sun, Jan 16, 2011 at 3:34 PM, Dominick Samperi <djsamp...@gmail.com>wrote: >> >>> It appears that this is a matter of compiler interpretation of the C++ >>> standards, >>> and it is not easy to see which compiler is correct (g++ or VC++). >>> >>> When I disable the VC++ work-around I get the following warning from this >>> compiler about the Plus_Vector_Vector constructor: >>> >>> c:\w\dev\stats\rbuild\Rcpp\inst\include\Rcpp/sugar/operators/plus.h(39): >>> warning C4413: >>> 'Rcpp::sugar::Plus_Vector_Vector<RTYPE,LHS_NA,LHS_T,RHS_NA,RHS_T>::lhs' : >>> reference member is initialized to a temporary that doesn't persist after >>> the constructor exits >>> >>> Obviously this is perfectly consistent with the kind of problem I >>> reported earlier in >>> this thread. What is not obvious is why the reference is initialized to >>> a temporary. >>> >>> I tried reproducing the problem (using VC++) with a simpler example taken >>> from >>> the Wiki page on expression templates. I simply added a get_ref() method >>> and used this in the VecDifference constructor initialization. There were >>> no >>> warnings and the program ran without problems, so the reason for the >>> warning in the case of Rcpp expression templates is not clear. >>> >>> The C++0x standard includes some changes in the way references are >>> handled. I don't know if this is relevant. >>> >>> Dominick >>> >>> >>> On Sat, Jan 15, 2011 at 10:55 PM, Dominick Samperi >>> <djsamp...@gmail.com>wrote: >>> >>>> Romain, >>>> >>>> I found a work-around for the VC++ problem. All I have to do >>>> is make sure the code that is currently ifdef-ed in Extractor.h >>>> is NOT enabled under VC++ (when _MSC_VER is defined). >>>> Currently this code is conditionally compiled with >>>> #ifndef IF_GCC_450_OR_LATER, so the additional condition >>>> that _MSC_VER is NOT defined must be added, and only >>>> the identity class at the top of Extractor.h is used. >>>> >>>> A comment in this file suggests that you have already >>>> observed problems under windows with Rcpp::Fast >>>> vector extraction, presumably with MinGW/g++. The >>>> comment goes on to say that it may be a g++ 4.5 >>>> issue and not a Windows issue. Obviously this thread >>>> has shown that this is not the complete story. >>>> >>>> I do not know why VC++ has a problem with >>>> Rcpp::Fast vector extraction. With all of the pointer >>>> manipulation it may have something to do with >>>> incompatible word sizes, memory alignment, >>>> or related low-level issues. >>>> >>>> Thanks, >>>> Dominick >>>> >>>> >>>> On Sat, Jan 15, 2011 at 2:27 PM, Dominick Samperi >>>> <djsamp...@gmail.com>wrote: >>>> >>>>> So that there is no confusion, I should add that the problems that I >>>>> report >>>>> here do not occur under Linux/g++ or under MinGW/g++ (the supported >>>>> environments), where Rcpp/sugar seems to work fine. >>>>> >>>>> >>>>> On Sat, Jan 15, 2011 at 1:23 PM, Dominick Samperi <djsamp...@gmail.com >>>>> > wrote: >>>>> >>>>>> >>>>>> >>>>>> On Sat, Jan 15, 2011 at 4:15 AM, Romain Francois < >>>>>> rom...@r-enthusiasts.com> wrote: >>>>>> >>>>>>> Le 13/01/11 16:29, Dominick Samperi a écrit : >>>>>>> >>>>>>> The template expression code is very interesting, but it >>>>>>>> does not work as expected under >>>>>>>> Windows/g++/MinGW/32bit/Rterm.exe. The problem >>>>>>>> does not appear when I use Rgui.exe, or if I use >>>>>>>> 64bit Windows! >>>>>>>> >>>>>>>> Consider the following C++ code called using >>>>>>>> .Call('testsugar',1:5,1:5): >>>>>>>> >>>>>>>> RcppExport SEXP testsugar(SEXP x_, SEXP y_) { >>>>>>>> Rcpp::NumericVector x(x_), y(y_); >>>>>>>> Rprintf("%d, %lf, %lf\n", (x+y).size(), (x+y)[0], (x+y)[1]); >>>>>>>> return R_NilValue; >>>>>>>> } >>>>>>>> >>>>>>>> Under Linux/GCC, or 64bit Windows/g++, or >>>>>>>> 32bit Windows/g++ I get the expected result: >>>>>>>> >>>>>>>> 5, 2.0, 4.0 >>>>>>>> >>>>>>>> Under Windows/32bit/Rterm.exe I get: >>>>>>>> >>>>>>>> 5, 0.0, 0.0 >>>>>>>> >>>>>>> >>>>>>> Intriguing. Maybe Rprintf is to blame. Can you try this instead: >>>>>> >>>>>> >>>>>>> >>>>>>> RcppExport SEXP testsugar(SEXP x_, SEXP y_) { >>>>>>> Rcpp::NumericVector x(x_), y(y_); >>>>>>> int n = (x+y).size() ; >>>>>>> double xy0 = (x+y)[0] ; >>>>>>> double xy1 = (x+y)[1] ; >>>>>>> Rprintf("%d, %lf, %lf\n", n, xy0, xy1); >>>>>>> return R_NilValue; >>>>>>> >>>>>>> } >>>>>>> >>>>>> >>>>>> Good guess, I found a problem with Rprintf yesterday, but this >>>>>> will not fix it. The problem is not caused by the arbitrary evaluation >>>>>> order of the arguments to Rprintf. It is caused by the different >>>>>> behavior of the format control "%lf" under different architectures! >>>>>> In particular, the problem goes away under i386/32bit Windows using >>>>>> MinGW/g++ when "%lf" is replaced with "%f". I could not find this >>>>>> documented anywhere. >>>>>> >>>>>> Of course, this has nothing to do with Rcpp, and it might >>>>>> be of interest to r-devel. >>>>>> >>>>>> For me this was just a distraction because the problem with >>>>>> Visual C++ is still alive and well and has nothing to do with >>>>>> Rprintf. As this information might be helpful in other >>>>>> (non-VC++) contexts here is what I am seeing. >>>>>> >>>>>> Consider: >>>>>> >>>>>> >>>>>> RcppExport SEXP testsugar(SEXP x_, SEXP y_) { >>>>>> Rcpp::NumericVector x(x_), y(y_); >>>>>> Rprintf("val = %f\n", (x+y)[0]); >>>>>> return R_NilValue; >>>>>> } >>>>>> >>>>>> This goes through operator+(lhs,rhs) in plus.h, which triggers the >>>>>> construction of an object of type Plus_Vector_Vector, and the >>>>>> construction seems to happen without problems, because the >>>>>> following Rprint's print what you would expect in the >>>>>> constructor: >>>>>> >>>>>> Rprintf("RTYPE = %d\n", RTYPE); // get 14, REALSXP >>>>>> Rprintf("size: %d, %d, %d\n", lhs.size(), rhs.size(), this->size()); >>>>>> // 5, 5, 5 >>>>>> Rprintf("vals: %f, %f, %f, %f\n", lhs[0], rhs[0], lhs[1], rhs[1]); // >>>>>> 1.0, 1.0, 2.0, 2.0 >>>>>> Rprintf("ptrs: %p, %p\n", &lhs, &rhs); // reasonable addresses >>>>>> >>>>>> But when you leave the constructor the two objects lhs and rhs get >>>>>> clobbered, even though their respective addresses seem not to >>>>>> change. In particular, the following print statements when inserted >>>>>> into operator[](int i) show garbage (and sometimes cause a crash): >>>>>> >>>>>> Rprintf("ptrs: %p, %p\n", &lhs, &rhs); // this is OK, same addresses >>>>>> as above >>>>>> Rprintf("lhs_ = %f\n", lhs_); // 0.0 or garbage >>>>>> Rprintf("rhs_ = %f\n", rhs_); // 0.0 or garbage >>>>>> Rprintf("size = %d\n", lhs.size()); // usually crashes. >>>>>> >>>>>> Dominick >>>>>> >>>>>> >>>>>>> (Under VC++ there are more serious problems including >>>>>>>> corruption of other in the wrap-up function >>>>>>>> Vector(VectorBase& other), but since VC++ is not >>>>>>>> supported I will not elaborate here.) >>>>>>>> >>>>>>>> Thanks, >>>>>>>> Dominick >>>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Romain Francois >>>>>>> Professional R Enthusiast >>>>>>> +33(0) 6 28 91 30 30 >>>>>>> http://romainfrancois.blog.free.fr >>>>>>> |- http://bit.ly/fT2rZM : highlight 0.2-5 >>>>>>> |- http://bit.ly/gpCSpH : Evolution of Rcpp code size >>>>>>> `- http://bit.ly/hovakS : RcppGSL initial release >>>>>>> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> Rcpp-devel mailing list >>>>>>> Rcpp-devel@lists.r-forge.r-project.org >>>>>>> >>>>>>> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel >>>>>>> >>>>>> >>>>>> >>>>> >>>> >>> >> >
_______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel