#include #include #include // See also addis.cc using namespace std; enum { ADD, SUB, MUL }; template struct BinExpr { template struct BasicType; template struct BasicType>; using ObjType = typename BasicType::ObjType; using value_type = typename ObjType::value_type; LHS const &d_lhs; RHS const &d_rhs; BinExpr(LHS const &lhs, RHS const &rhs) : d_lhs(lhs), d_rhs(rhs) {} size_t size() const { return d_lhs.size(); } template struct Operation; value_type operator[](size_t ix) const { return Operation::cpt(d_lhs[ix], d_rhs[ix]); // *************** this causes // calling // the proper // cpt **************** } operator ObjType() const { ObjType retVal; retVal.reserve(size()); for (size_t ix = 0, end = size(); ix != end; ++ix) new(&retVal[ix]) value_type{ (*this)[ix] }; return retVal; } }; template template struct BinExpr::BasicType { using ObjType = Type; }; template template struct BinExpr::BasicType> { using ObjType = typename BinExpr::ObjType; }; template template struct BinExpr::Operation { static value_type cpt(value_type const &lhs, value_type const &rhs) { return lhs + rhs; }; }; template template struct BinExpr::Operation { static value_type cpt(value_type const &lhs, value_type const &rhs) { return lhs - rhs; }; }; template BinExpr operator+(LHS const &lhs, RHS const &rhs) { return BinExpr(lhs, rhs); } template BinExpr operator-(LHS const &lhs, RHS const &rhs) { return BinExpr(lhs, rhs); } struct VI // define the data structure to { // operate on static size_t s_count; using value_type = int; VI() = default; VI(VI const &other) { (*this)[0] = other[0]; cout << "CC, count = " << s_count << '\n'; } VI(VI &&tmp) { (*this)[0] = tmp[0]; cout << "MC, count = " << s_count << '\n'; } int d_value = 0; size_t size() const { return 1; }; void reserve(size_t count) {}; int &operator[](size_t idx) { ++s_count; return d_value; } int const &operator[](size_t idx) const { ++s_count; return d_value; } }; size_t VI::s_count; int main() { VI a, b, c, d; VI e = a + b + c + d; // (a + b + c + d).operator VI(); // the resulting sum is computed once // the conversion operator is called. // static_cast(a + b + c + d); cout << "# index computations: " << VI::s_count << '\n'; }