/**
1. Define template<typename T> struct S { T val; };.
2. Add a constructor, so that you can initialize with a T.
3. Define variables of types S<int>, S<char>, S<double>,
S<string>, and S<vector<int>>;
initialize them with values of your choice.
4. Read those values and print them.
5. Add a function template get() that returns a
reference to val.
6. Put the definition of get() outside the class.
7. Make val private.
8. Do 4 again using get().
9. Add a set() function template so that you can change val.
10. Replace set() with an S<T>::operator=(const T&).
Hint: Much simpler than §19.2.5.
11. Provide const and non-const versions of get().
12. Define a function template<typename T> read_val(T& v)
that reads from cin into v.
13. Use read_val() to read into each of the variables from
3 except the S<vector<int>> variable.
14. Bonus: Define input and output operators (>> and <<)
for vector<T>s. For both input and
output use a { val, val, val } format.
That will allow read_val() to also handle the
S<vector<int>> variable.
*/
#include<string>
#include<vector>
#include<iostream>
using namespace std;

template<typename T>
class S {
private:
    T val;
public :
    S(T t) : val(t) {};
    T& get();
    const T& get() const;
    void set(T t) { val = t; }
    T& operator=(T t) { this->val = t; }
    T& read_val(T& v) {
        cin >> val;
        return val;
    }
};

template<typename T>
T& S<T>::get() {  return val; }

template<typename T>
const T& S<T>::get() const {  return val; }

template<typename U>
ostream& operator<<(ostream& os, const vector<U>& vi) {
    cout << '{';
    for(int i = 0; i < vi.size()-1; ++i)
        cout << vi[i] << ", ";
    cout << vi[vi.size()-1] << '}';
    return os;
}

template<typename T>
istream& operator>>(istream& is, vector<T>& vi) {
    char c;
    T t;
    cin >> c; // EAT THE {
    cin>>c;
    while(c!='}') {
        if(c!=',')
            cin.unget(); /// eat the comma
        cin >> t;
        vi.push_back(t);
        cin>>c;
    }
    return is;
}

template<typename T>
T& read_val(T& v) {
    cin >> v;
}

int main() {
    int i{0};
    S<int> s{1};
    const S<char> c('a');
    S<double> d(1.0e0);
    S<string> str("stringythingy");
    S<vector<int> > vi{{1,2,3}};
    cout << "\ns = " << s.get();
    cout << "\nChange s to: ";
    cin >> i;
    s.set(i);
    cout << "\nNow s = " << s.get();
    cout << "\nChange s to: ";
    s.read_val(i);
    cout << "\nNow s = " << s.get();
    cout << "\nc = " << c.get();
    cout << "\nd = " << d.get();
    cout << "\nstr = " << str.get();
    cout << "\nvi = " << vi.get() << vi.get();
    cout << "\ns's val is " << s.get();
    cout << "\nEnter a new vector for vi: ";
    vector<int> vInts;
    cin >> vInts;
    ///vi = {10,20,30};
    cout << "\nvInts = " << vInts;
}
