#include <iostream> #include <iomanip> #include <map> #include <vector> #include <string> using namespace std; template<class C, class T> auto contains(const C& v, const T& x) -> decltype(end(v), true) { return end(v) != std::find(begin(v), end(v), x); } template <class... Types> constexpr inline __attribute__((__always_inline__)) int UNUSED(Types&&...) { return 0; }; map<string, map<string, string>> res; vector<string> froms; vector<string> tos; string from; string to; void report(string st) { if (!from.empty() && !to.empty()) { res[from][to] += st; } cout << st << " "; } struct T { T() { report("Dc"); } T(int va) : a(va) { report("Pc"); } T(const T& other) : a(other.a) { report("Cc"); } T(T&& other) : a(std::exchange(other.a, 0)) { report("Mc"); } T& operator=(int va) { report("Va"); a = va; return *this; } T& operator=(const T& rhs) { report("Ca"); // check for self-assignment if(&rhs == this) return *this; a = rhs.a; return *this; } T& operator=(T&& rhs) { report("Ma"); // check for self-assignment if(&rhs == this) return *this; a = std::exchange(rhs.a, 0); return *this; } ~T() { report("D"); } int a = 1; }; T Fprv() { return T(); } const T Fcprv() { return T(); } void print_col(const string &st, int width) { cout << endl << left << setw(width) << st; } void test_assign(string lto, string lfrom) { from = lfrom; to = lto; res[from][to] = ""; if (!from.empty() && !to.empty()) { if (!contains(froms, from)) froms.push_back(from); if (!contains(tos, to)) tos.push_back(to); } print_col(lto + " = " + lfrom + ": ", 20); } #define TEST_ASSIGN(t, v) { \ test_assign(#t, #v); \ ts = v; \ cout << sa; \ UNUSED(s); \ cout << "-"; \ } void test_conversion() { T l; const T cl; T& lr = l; const T& clr = l; T&& rr = T(); const T&& crr = T(); auto &&fr = T(); TEST_ASSIGN(T, 8); TEST_ASSIGN(T, T()); TEST_ASSIGN(T, l); TEST_ASSIGN(T, move(l)); TEST_ASSIGN(T, cl); TEST_ASSIGN(T, move(cl)); TEST_ASSIGN(T, lr); TEST_ASSIGN(T, move(lr)); TEST_ASSIGN(T, clr); TEST_ASSIGN(T, move(clr)); TEST_ASSIGN(T, rr); TEST_ASSIGN(T, move(rr)); TEST_ASSIGN(T, crr); TEST_ASSIGN(T, move(crr)); TEST_ASSIGN(T, Fcprv()); TEST_ASSIGN(T, Fprv()); TEST_ASSIGN(T, fr); TEST_ASSIGN(T, move(fr)); TEST_ASSIGN(const T, 8); TEST_ASSIGN(const T, T()); TEST_ASSIGN(const T, l); TEST_ASSIGN(const T, move(l)); TEST_ASSIGN(const T, cl); TEST_ASSIGN(const T, move(cl)); TEST_ASSIGN(const T, lr); TEST_ASSIGN(const T, move(lr)); TEST_ASSIGN(const T, clr); TEST_ASSIGN(const T, move(clr)); TEST_ASSIGN(const T, rr); TEST_ASSIGN(const T, move(rr)); TEST_ASSIGN(const T, crr); TEST_ASSIGN(const T, move(crr)); TEST_ASSIGN(const T, Fcprv()); TEST_ASSIGN(const T, Fprv()); TEST_ASSIGN(const T, fr); TEST_ASSIGN(const T, move(fr)); //TEST_ASSIGN(T&, 8); //TEST_ASSIGN(T&, T()); TEST_ASSIGN(T&, l); //TEST_ASSIGN(T&, move(l)); //TEST_ASSIGN(T&, cl); //TEST_ASSIGN(T&, move(cl)); TEST_ASSIGN(T&, lr); //TEST_ASSIGN(T&, move(lr)); //TEST_ASSIGN(T&, clr); //TEST_ASSIGN(T&, move(clr)); //TEST_ASSIGN(T&, rr); //TEST_ASSIGN(T&, move(rr)); //TEST_ASSIGN(T&, crr); //TEST_ASSIGN(T&, move(crr)); //TEST_ASSIGN(T&, Fcprv()); //TEST_ASSIGN(T&, Fprv()); TEST_ASSIGN(T&, fr); //TEST_ASSIGN(T&, move(fr)); TEST_ASSIGN(const T&, 8); TEST_ASSIGN(const T&, T()); TEST_ASSIGN(const T&, l); TEST_ASSIGN(const T&, move(l)); TEST_ASSIGN(const T&, cl); TEST_ASSIGN(const T&, move(cl)); TEST_ASSIGN(const T&, lr); TEST_ASSIGN(const T&, move(lr)); TEST_ASSIGN(const T&, clr); TEST_ASSIGN(const T&, move(clr)); TEST_ASSIGN(const T&, rr); TEST_ASSIGN(const T&, move(rr)); TEST_ASSIGN(const T&, crr); TEST_ASSIGN(const T&, move(crr)); TEST_ASSIGN(const T&, Fcprv()); TEST_ASSIGN(const T&, Fprv()); TEST_ASSIGN(const T&, fr); TEST_ASSIGN(const T&, move(fr)); TEST_ASSIGN(T&&, 8); TEST_ASSIGN(T&&, T()); //TEST_ASSIGN(T&&, l); TEST_ASSIGN(T&&, move(l)); //TEST_ASSIGN(T&&, cl); //TEST_ASSIGN(T&&, move(cl)); //TEST_ASSIGN(T&&, lr); TEST_ASSIGN(T&&, move(lr)); //TEST_ASSIGN(T&&, clr); //TEST_ASSIGN(T&&, move(clr)); //TEST_ASSIGN(T&&, rr); TEST_ASSIGN(T&&, move(rr)); //TEST_ASSIGN(T&&, crr); //TEST_ASSIGN(T&&, move(crr)); //TEST_ASSIGN(T&&, Fcprv()); TEST_ASSIGN(T&&, Fprv()); //TEST_ASSIGN(T&&, fr); TEST_ASSIGN(T&&, move(fr)); TEST_ASSIGN(const T&&, 8); TEST_ASSIGN(const T&&, T()); //TEST_ASSIGN(const T&&, l); TEST_ASSIGN(const T&&, move(l)); //TEST_ASSIGN(const T&&, cl); TEST_ASSIGN(const T&&, move(cl)); //TEST_ASSIGN(const T&&, lr); TEST_ASSIGN(const T&&, move(lr)); //TEST_ASSIGN(const T&&, clr); TEST_ASSIGN(const T&&, move(clr)); //TEST_ASSIGN(const T&&, rr); TEST_ASSIGN(const T&&, move(rr)); //TEST_ASSIGN(const T&&, crr); TEST_ASSIGN(const T&&, move(crr)); TEST_ASSIGN(const T&&, Fcprv()); TEST_ASSIGN(const T&&, Fprv()); //TEST_ASSIGN(const T&&, fr); TEST_ASSIGN(const T&&, move(fr)); //TEST_ASSIGN(auto&, T{8}); //TEST_ASSIGN(auto&, T()); TEST_ASSIGN(auto&, l); //TEST_ASSIGN(auto&, move(l)); TEST_ASSIGN(auto&, cl); TEST_ASSIGN(auto&, move(cl)); TEST_ASSIGN(auto&, lr); //TEST_ASSIGN(auto&, move(lr)); TEST_ASSIGN(auto&, clr); TEST_ASSIGN(auto&, move(clr)); TEST_ASSIGN(auto&, rr); //TEST_ASSIGN(auto&, move(rr)); TEST_ASSIGN(auto&, crr); TEST_ASSIGN(auto&, move(crr)); TEST_ASSIGN(auto&, Fcprv()); //TEST_ASSIGN(auto&, Fprv()); TEST_ASSIGN(auto&, fr); //TEST_ASSIGN(auto&, move(fr)); TEST_ASSIGN(const auto&, T{8}); TEST_ASSIGN(const auto&, T()); TEST_ASSIGN(const auto&, l); TEST_ASSIGN(const auto&, move(l)); TEST_ASSIGN(const auto&, cl); TEST_ASSIGN(const auto&, move(cl)); TEST_ASSIGN(const auto&, lr); TEST_ASSIGN(const auto&, move(lr)); TEST_ASSIGN(const auto&, clr); TEST_ASSIGN(const auto&, move(clr)); TEST_ASSIGN(const auto&, rr); TEST_ASSIGN(const auto&, move(rr)); TEST_ASSIGN(const auto&, crr); TEST_ASSIGN(const auto&, move(crr)); TEST_ASSIGN(const auto&, Fcprv()); TEST_ASSIGN(const auto&, Fprv()); TEST_ASSIGN(const auto&, fr); TEST_ASSIGN(const auto&, move(fr)); TEST_ASSIGN(auto&&, T{8}); TEST_ASSIGN(auto&&, T()); TEST_ASSIGN(auto&&, l); TEST_ASSIGN(auto&&, move(l)); TEST_ASSIGN(auto&&, cl); TEST_ASSIGN(auto&&, move(cl)); TEST_ASSIGN(auto&&, lr); TEST_ASSIGN(auto&&, move(lr)); TEST_ASSIGN(auto&&, clr); TEST_ASSIGN(auto&&, move(clr)); TEST_ASSIGN(auto&&, rr); TEST_ASSIGN(auto&&, move(rr)); TEST_ASSIGN(auto&&, crr); TEST_ASSIGN(auto&&, move(crr)); TEST_ASSIGN(auto&&, Fcprv()); TEST_ASSIGN(auto&&, Fprv()); TEST_ASSIGN(auto&&, fr); TEST_ASSIGN(auto&&, move(fr)); TEST_ASSIGN(const auto&&, T{8}); TEST_ASSIGN(const auto&&, T()); //TEST_ASSIGN(const auto&&, l); TEST_ASSIGN(const auto&&, move(l)); //TEST_ASSIGN(const auto&&, cl); TEST_ASSIGN(const auto&&, move(cl)); //TEST_ASSIGN(const auto&&, lr); TEST_ASSIGN(const auto&&, move(lr)); //TEST_ASSIGN(const auto&&, clr); TEST_ASSIGN(const auto&&, move(clr)); //TEST_ASSIGN(const auto&&, rr); TEST_ASSIGN(const auto&&, move(rr)); //TEST_ASSIGN(const auto&&, crr); TEST_ASSIGN(const auto&&, move(crr)); TEST_ASSIGN(const auto&&, Fcprv()); TEST_ASSIGN(const auto&&, Fprv()); //TEST_ASSIGN(const auto&&, fr); TEST_ASSIGN(const auto&&, move(fr)); cout << endl; const int twidth = 9; cout << left << setw(twidth) << "From:"; for (const auto& lto : tos) { cout << left << setw(twidth) << lto; } cout << endl; for (const auto& lfrom : froms) { cout << left << setw(twidth) << lfrom; for (const auto& lto : tos) { if (!res.count(lfrom) || !res[lfrom].count(lto)) { cout << left << setw(twidth) << "-"; } else if (res[lfrom][lto].empty()) { cout << left << setw(twidth) << "+"; } else { cout << left << setw(twidth) << res[lfrom][lto]; } } cout << endl; } cout << endl; } int main() { test_conversion(); cout << endl; return 0; } /* Output: Dc Dc Dc Dc Dc T = 8: Pc 8-D T = T(): Dc 1-D T = l: Cc 1-D T = move(l): Mc 1-D T = cl: Cc 1-D T = move(cl): Cc 1-D T = lr: Cc 0-D T = move(lr): Mc 0-D T = clr: Cc 0-D T = move(clr): Cc 0-D T = rr: Cc 1-D T = move(rr): Mc 1-D T = crr: Cc 1-D T = move(crr): Cc 1-D T = Fcprv(): Dc 1-D T = Fprv(): Dc 1-D T = fr: Cc 1-D T = move(fr): Mc 1-D const T = 8: Pc 8-D const T = T(): Dc 1-D const T = l: Cc 0-D const T = move(l): Mc 0-D const T = cl: Cc 1-D const T = move(cl): Cc 1-D const T = lr: Cc 0-D const T = move(lr): Mc 0-D const T = clr: Cc 0-D const T = move(clr): Cc 0-D const T = rr: Cc 0-D const T = move(rr): Mc 0-D const T = crr: Cc 1-D const T = move(crr): Cc 1-D const T = Fcprv(): Dc 1-D const T = Fprv(): Dc 1-D const T = fr: Cc 0-D const T = move(fr): Mc 0-D T& = l: 0- T& = lr: 0- T& = fr: 0- const T& = 8: Pc 8-D const T& = T(): Dc 1-D const T& = l: 0- const T& = move(l): 0- const T& = cl: 1- const T& = move(cl): 1- const T& = lr: 0- const T& = move(lr): 0- const T& = clr: 0- const T& = move(clr): 0- const T& = rr: 0- const T& = move(rr): 0- const T& = crr: 1- const T& = move(crr): 1- const T& = Fcprv(): Dc 1-D const T& = Fprv(): Dc 1-D const T& = fr: 0- const T& = move(fr): 0- T&& = 8: Pc 8-D T&& = T(): Dc 1-D T&& = move(l): 0- T&& = move(lr): 0- T&& = move(rr): 0- T&& = Fprv(): Dc 1-D T&& = move(fr): 0- const T&& = 8: Pc 8-D const T&& = T(): Dc 1-D const T&& = move(l): 0- const T&& = move(cl): 1- const T&& = move(lr): 0- const T&& = move(clr): 0- const T&& = move(rr): 0- const T&& = move(crr): 1- const T&& = Fcprv(): Dc 1-D const T&& = Fprv(): Dc 1-D const T&& = move(fr): 0- auto& = l: 0- auto& = cl: 1- auto& = move(cl): 1- auto& = lr: 0- auto& = clr: 0- auto& = move(clr): 0- auto& = rr: 0- auto& = crr: 1- auto& = move(crr): 1- auto& = Fcprv(): Dc 1-D auto& = fr: 0- const auto& = T{8}: Pc 8-D const auto& = T(): Dc 1-D const auto& = l: 0- const auto& = move(l): 0- const auto& = cl: 1- const auto& = move(cl): 1- const auto& = lr: 0- const auto& = move(lr): 0- const auto& = clr: 0- const auto& = move(clr): 0- const auto& = rr: 0- const auto& = move(rr): 0- const auto& = crr: 1- const auto& = move(crr): 1- const auto& = Fcprv(): Dc 1-D const auto& = Fprv(): Dc 1-D const auto& = fr: 0- const auto& = move(fr): 0- auto&& = T{8}: Pc 8-D auto&& = T(): Dc 1-D auto&& = l: 0- auto&& = move(l): 0- auto&& = cl: 1- auto&& = move(cl): 1- auto&& = lr: 0- auto&& = move(lr): 0- auto&& = clr: 0- auto&& = move(clr): 0- auto&& = rr: 0- auto&& = move(rr): 0- auto&& = crr: 1- auto&& = move(crr): 1- auto&& = Fcprv(): Dc 1-D auto&& = Fprv(): Dc 1-D auto&& = fr: 0- auto&& = move(fr): 0- const auto&& = T{8}: Pc 8-D const auto&& = T(): Dc 1-D const auto&& = move(l): 0- const auto&& = move(cl): 1- const auto&& = move(lr): 0- const auto&& = move(clr): 0- const auto&& = move(rr): 0- const auto&& = move(crr): 1- const auto&& = Fcprv(): Dc 1-D const auto&& = Fprv(): Dc 1-D const auto&& = move(fr): 0- From: T const T T& const T& T&& const T&&auto& const auto&auto&& const auto&& 8 PcD PcD - PcD PcD PcD - - - - T() DcD DcD - DcD DcD DcD - DcD DcD DcD l CcD CcD + + - - + + + - move(l) McD McD - + + + - + + + cl CcD CcD - + - - + + + - move(cl) CcD CcD - + - + + + + + lr CcD CcD + + - - + + + - move(lr) McD McD - + + + - + + + clr CcD CcD - + - - + + + - move(clr)CcD CcD - + - + + + + + rr CcD CcD - + - - + + + - move(rr) McD McD - + + + - + + + crr CcD CcD - + - - + + + - move(crr)CcD CcD - + - + + + + + Fcprv() DcD DcD - DcD - DcD DcD DcD DcD DcD Fprv() DcD DcD - DcD DcD DcD - DcD DcD DcD fr CcD CcD + + - - + + + - move(fr) McD McD - + + + - + + + T{8} - - - - - - - PcD PcD PcD DDDDD */