reimplement, and add template