C++テンプレートのメモ

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