#include <cstddef>
#include <iostream>

template<typename Dst,typename Src>
Dst* pointer_cast(Src *ptr){
    return static_cast<Dst*>(static_cast<void*>(ptr));
}
template<typename Dst,typename Src>
Dst* pointer_cast(Src const* ptr){
    return static_cast<Dst*>(static_cast<void const*>(ptr));
}

class Vector{
protected:
    char *data;
    std::size_t elem_size;
    
    Vector(std::size_t size) : data(new char[3*size]),elem_size(size){
    }
    
    char *at(std::size_t index){
        return data + elem_size * index;
    }
    char const* at(std::size_t index) const{
        return data + elem_size * index;
    }

    void doSomething();
};
void Vector::doSomething(){
    //処理が隠蔽できる
}
template<typename T>
class Vector_ : Vector{
public:
    Vector_() : Vector(sizeof(T)){
    }
    
    T &operator [](std::size_t index){
        return *pointer_cast<T>(this->at(index));
    }
    T const& operator[](std::size_t index) const{
        return *pointer_cast<T const>(this->at(index));
    }
};
template<typename T>
std::ostream& operator <<(std::ostream& os,Vector_<T> const& v){
    return os << '[' << v[0] <<  ',' << v[1] << ',' << v[2] << ']';
}

int main(){
    Vector_<int> v;
    v[0] = 1;
    v[1] = 2;
    v[2] = 3;
    std::cout << v << std::endl;
    
    Vector_<double> v2;
    v2[0] = 0.0;
    v2[1] = 3.14;
    v2[2] = 2.71;
    std::cout << v2 << std::endl;
    return 0;
}
