I took a some time re-working the operators header based on previous feedback provided. Hopefully this will allow us to get a rough base worked out and we can work through some of the details. Most of the general idea is the same as v1, but there are a few changes and in general is not backwards-compatible. As far as I know this should be usable and support at least all of the features provided by v1 or something equivalent (see notes). codepad link: http://codepad.org/F2LrIUD2 notes: 1. Rather than using op1/op2, this version uses template specialization to make the distinction between the two. 2. All math operators have commutative and non-commutative versions, as well as left versions. Distinction is made by struct name, i.e. op is non- commutative, op_commutative is commutative, and op_left is the left variation. Note that there isn't any hard checks to prevent op_left<T, T> (which obviously makes no sense, may even result in a compiler error regardless), but the internal composite operators all use template partial specialization which don't have op_left if U = T. 3. I opted for the return-by-value only method to safely handle move semantics (see other discussion Daniel started for why). Changing this to the unsafe version is as simple as replacing the basic operator definition macro (I have that code, too. Let me know if I should post this, too). 4. Pretty much all code which alluded to a specific compiler bug/support has been removed. This includes NRVO code. I'm still not sure what level of backwards-compatibility or specific compiler code we wanted so I just code to C++03/C++11. 5. I haven't added noexcept yet (mainly because I haven't had the time to learn more about noexcept yet). My testing has nearly all so far been done in VS2012 which has an "illustrious reputation" with standards compliance. I also have access to VS2010 and MinGW (GCC 4.7.2) so I'll try testing these later, but I don't have a setup for testing compilers in Linux/Unix/Mac or any other compilers we may want to support (Clang, Intel, Embarcadero/Borland, etc.). A few questions I have: 1. In v1 operators were always considered commutative/non-commutative. The composite operators take advantage of this fact, and I have the composite operators implemented with the same assumptions. Are there any composite operators we want to provide which make different assumptions (for example, a matrix has commutative add/subtract, but non-commutative multiply)? 2. I'm a little unsure if the <boost/iterator.hpp> include is still required. It compiled fine without it, but I haven't tried out all the features to see if it is indeed required. Anyone know why we should keep this include in v2? Feedback would be appreciated, thanks.
Oops, major typos in macro fixed (missing code to propagate operator inheritance chain for rvalue ref aware compilers). Revised codepad: http://codepad.org/pZXpLKgp
On Friday 26 April 2013 05:47:12 Andrew Ho wrote:
Oops, major typos in macro fixed (missing code to propagate operator inheritance chain for rvalue ref aware compilers).
Revised codepad:
1. BOOST_HAS_RVALUE_REFS is deprecated, use BOOST_NO_CXX11_RVALUE_REFERENCES instead. 2. I think you're not guaranteed to have std::move even if you have rvalue references. If I'm not mistaken, folks on OS X have that situation when they compile with clang and libstdc++ from gcc 4.2. I would suggest using boost::move instead (include boost/move/utility.hpp). 3. I think there's an error in NAME##_left of the BOOST_BINARY_OPERATOR define, when BOOST_HAS_RVALUE_REFS is not defined. The nrv variable construction fused with the operator invokation.
Thanks for 1) and 3), they've been changed.
2. I think you're not guaranteed to have std::move even if you have rvalue references. If I'm not mistaken, folks on OS X have that situation when they compile with clang and libstdc++ from gcc 4.2. I would suggest using boost::move instead (include boost/move/utility.hpp).
Ok, I can make this change but this makes me wonder can we/should we try to implement move-aware operators which can be used with C++03? I haven't looked too much into boost.move, but they do suggest it's possible to implement move semantics to be portable between C++03/C++11.
I have a prototype for boost.move integration done: http://codepad.org/O5LljVkn
From what I can tell, boost.move uses C++11 features if available, and if not, uses a C++03 work-around (slight overhead if boost.move is used). I tested with MinGW GCC 4.7.2 (-std=c++03 and -std=c++11) and VS2012. If no move constructor is available, the code correctly resorts back to copy constructors.
One bonus of going this route is there are no compiler feature macro checks required in boost.operators since boost.move already takes care of this.
participants (2)
-
Andrew Ho
-
Andrey Semashev