struct reporter {
reporter() {
cout << "construct" << endl;
}
~reporter() {
cout << "destruct" << endl;
}
reporter(const reporter &) {
cout << "copy" << endl;
}
reporter(reporter &&) {
cout << "move" << endl;
}
reporter &operator =(const reporter &) {
cout << "copy" << endl;
return *this;
}
reporter &operator =(reporter &&) {
cout << "move" << endl;
return *this;
}
};
using type = reporter;
template <typename T>
void f1(T) {
cout << "f1(T)" << endl;
cout << "type \t" << is_same_v<T, type> << endl;
cout << "type & \t" << is_same_v<T, type &> << endl;
cout << "type && \t" << is_same_v<T, type &&> << endl;
cout << "type * \t" << is_same_v<T, type *> << endl;
cout << "type[1] \t" << is_same_v<T, type[1]> << endl;
cout << "type(&)[1] \t" << is_same_v<T, type(&)[1]> << endl;
cout << "type(&&)[1]\t" << is_same_v<T, type(&&)[1]> << endl;
cout << endl;
}
template <typename T>
void f2(T&) {
cout << "f2(T&)" << endl;
cout << "type \t" << is_same_v<T, type> << endl;
cout << "type & \t" << is_same_v<T, type &> << endl;
cout << "type && \t" << is_same_v<T, type &&> << endl;
cout << "type * \t" << is_same_v<T, type *> << endl;
cout << "type[1] \t" << is_same_v<T, type[1]> << endl;
cout << "type(&)[1] \t" << is_same_v<T, type(&)[1]> << endl;
cout << "type(&&)[1]\t" << is_same_v<T, type(&&)[1]> << endl;
cout << endl;
}
template <typename T>
void f3(T&&) {
cout << "f3(T&&)" << endl;
cout << "type \t" << is_same_v<T, type> << endl;
cout << "type & \t" << is_same_v<T, type &> << endl;
cout << "type && \t" << is_same_v<T, type &&> << endl;
cout << "type * \t" << is_same_v<T, type *> << endl;
cout << "type[1] \t" << is_same_v<T, type[1]> << endl;
cout << "type(&)[1] \t" << is_same_v<T, type(&)[1]> << endl;
cout << "type(&&)[1]\t" << is_same_v<T, type(&&)[1]> << endl;
cout << endl;
}
int main() {
cout << "type" << endl;
type v;
f1(v);
f2(v);
f3(v);
cout << "type &" << endl;
type &r1 = v;
f1(r1);
f2(r1);
f3(r1);
cout << "type &&" << endl;
type &&r2 = type();
f1(r2);
f2(r2);
f3(r2);
cout << "type *" << endl;
type *p = nullptr;
f1(p);
f2(p);
f3(p);
cout << "type[]" << endl;
type a[1];
f1(a);
f2(a);
f3(a);
}
type
construct
copy
f1(T)
type 1
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
destruct
f2(T&)
type 1
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
f3(T&&)
type 0
type & 1
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
type &
copy
f1(T)
type 1
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
destruct
f2(T&)
type 1
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
f3(T&&)
type 0
type & 1
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
type &&
construct
copy
f1(T)
type 1
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
destruct
f2(T&)
type 1
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
f3(T&&)
type 0
type & 1
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
type *
f1(T)
type 0
type & 0
type && 0
type * 1
type[1] 0
type(&)[1] 0
type(&&)[1] 0
f2(T&)
type 0
type & 0
type && 0
type * 1
type[1] 0
type(&)[1] 0
type(&&)[1] 0
f3(T&&)
type 0
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 0
type(&&)[1] 0
type[]
construct
f1(T)
type 0
type & 0
type && 0
type * 1
type[1] 0
type(&)[1] 0
type(&&)[1] 0
f2(T&)
type 0
type & 0
type && 0
type * 0
type[1] 1
type(&)[1] 0
type(&&)[1] 0
f3(T&&)
type 0
type & 0
type && 0
type * 0
type[1] 0
type(&)[1] 1
type(&&)[1] 0
destruct
destruct
destruct