c++ - Differentiate between 1D and 2D container in template class constructor (SFINAE) -
so, have class, has array of arrays private member. wish have 2 constructors each case (1d or 2d). of course declaration happens same, template deduction can't job without me doing it. here's code:
edit: need work stl containers vector or c++ array. why overcomplicating , not going "arrays" fix.
#include <iostream> #include <array> template<class t, std::size_t rows_t, std::size_t cols_t> class test { private: std::array<std::array<t, cols_t>, rows_t> _data; public: auto begin() { return this->_data.begin(); } auto end() { return this->_data.end(); } //constructor template<class type_t> test(const type_t &arr) { std::size_t j = 0; (const auto &num : arr) this->_data[0][j++] = num; } template<class type_t> test(const type_t &arr) { std::size_t = 0; (const auto &el : arr) { std::size_t j = 0; (const auto &num : el) this->_data[i][j++] = num; ++i; } } }; int main() { double arr[3] = { 1, 2, 3 }; double arr2[2][2] = { {1, 2}, {3, 4} }; test<double, 1, 3> obj = arr; test<double, 2, 2> obj2 = arr2; (const auto &i : obj2) { (const auto &j : i) std::cout << j << " "; std::cout << std::endl; } std::cin.get(); }
note: i've been reading enable_if
, don't quite understand how works. can done that?
first, have "teach" compiler what's 2d , what's not. hence, have define following type trait:
template<typename t> struct is2d : public std::false_type {}; template<typename t, std::size_t n, std::size_t m> struct is2d<std::array<std::array<t, m>, n>> : std::true_type {}; template<typename t> struct is2d<std::vector<std::vector<t>>> : std::true_type {}; template<typename t, std::size_t n, std::size_t m> struct is2d<t[n][m]> : std::true_type {};
then set class definition in following way:
template<class t, std::size_t rows_t, std::size_t cols_t> class test{ std::array<std::array<t, cols_t>, rows_t> _data; template<class type_t> std::enable_if_t<!is2d<type_t>::value, void> test_init(type_t const &arr) { std::size_t j = 0; (const auto &num : arr) _data[0][j++] = num; } template<class type_t> std::enable_if_t<is2d<type_t>::value, void> test_init(type_t const &arr) { std::size_t = 0; for(const auto &el : arr) { std::size_t j = 0; (const auto &num : el) _data[i][j++] = num; ++i; } } public: auto &operator[](const std::size_t &i) { return this->_data[i]; } auto begin() { return this->_data.begin(); } auto end() { return this->_data.end(); } //constructor template<class type_t> test(type_t const &arr) { test_init(arr); } };
Comments
Post a Comment