2016-10-10 61 views
4

我有一個矩陣類,我想打印到不同的矩陣類型(int,float,double)不同的矩陣到終端。我想實現這一點:如果矩陣類型,如果floatdouble,打印矩陣使用printf("%.3f ",matrix[i][j]) 成員專業化的模板類爲組類?

  • 否則如果矩陣類型,如果int,打印矩陣使用printf("%d ",matrix[i][j])
    • ,拋出一個錯誤

    以下是我所擁有的相關部分:

    ... 
    
    template <class T> 
    class Matrix2D { 
    private: 
        std::vector< std::vector<T> > matrix; 
    public: 
        ... 
        void print() const; // print the whole matrix 
    } 
    
    ... 
    
    template <class T> 
    void Matrix2D<T>::print() const { 
        // throw an error 
    } 
    
    template <> 
    void Matrix2D<int>::print() const { 
        // print matrix using printf("%d ",matrix[i][j]) 
    } 
    
    template <> 
    void Matrix2D<float,double>::print() const { 
        // print matrix using printf("%.3f ",matrix[i][j]) 
    } 
    

    但使用Matrix2D<float,double>給我錯誤信息error: wrong number of template arguments (2, should be 1)。但是,我希望floatdouble型矩陣具有共同的print()函數(不希望兩次複製相同的東西)。達到此目的最簡單的方法是什麼?謝謝!

  • 回答

    2

    只是作爲一個替代方案提出的解決方案模板,使用舊的好函數重載:

    public: 
        void print() const 
        { 
         for (auto const& row : matrix) 
          for (auto const& v : row) 
           print(v); 
        } 
    
    private: 
        static void print(int val) 
        { 
         printf("%d ", val); 
        } 
    
        static void print(float val) 
        { 
         printf("%.3f", val); 
        } 
    
    +0

    這是我落得這樣做吧。這是一個輕量級解決方案,避免了額外的庫。我可以將大部分的顯示功能寫入一塊,並調用此重載打印功能,從而最大限度地減少額外的代碼寫入。 –

    0

    你可以使用enable_iftype traits,不要做這樣的事情:

    template<class T> class MyClass 
    { 
    public: 
        // this one will be created if the argument is of a floating point type, i.e. 
        // double or float 
        template<typename U = T> 
        typename std::enable_if<std::is_floating_point<U>::value, void>::type 
        print(U v) 
        { 
         std::cout << "float" << std::endl; 
        } 
    
        // this one will be created if the argument is of an integral type, i.e. 
        // bool, char, char16_t, char32_t, wchar_t, short, int, long, long long 
        template<typename U = T> 
        typename std::enable_if<std::is_integral<U>::value, void>::type 
        print(U v) 
        { 
         std::cout << "integer" << std::endl; 
        } 
    
    }; 
    
    
    int main() { 
        MyClass<int>c; 
        c.print(1); 
        c.print(1.f); 
    } 
    

    輸出:

    integer 
    float 
    
    1

    了一個問題,問想Matrix2D<short>::print()拋出一個錯誤。爲了達到這個目的,你可以使用標籤調度。

    標籤 - 簡單

    天真的方法需要你專門標記爲每種類型的直接。

    namespace detail 
    { 
    
    struct int_tag{}; 
    struct float_tag{}; 
    struct error_tag{}; 
    
    template<typename T> struct choose_tag { using type = error_tag; }; 
    
    template<> struct choose_tag<int> { using type = int_tag; }; 
    template<> struct choose_tag<double> { using type = float_tag; }; 
    template<> struct choose_tag<float> { using type = float_tag; }; 
    
    template<typename T> 
    using tag = typename choose_tag<T>::type; 
    
    } 
    

    標籤 - 類型列表

    你可以用Boost.Hana(或其他MPL溶液)避免這種情況。首先,在名單確定檢查的類型:

    template<typename T, typename... Us> 
    constexpr bool contains = 
         hana::any_of(hana::tuple_t<Us...>, hana::partial(hana::equal, hana::type_c<T>))(); 
    

    然後,只需enable_if這類型的標籤:

    template<typename T, typename = std::void_t<>> 
    struct choose_tag 
    { using type = error_tag; }; 
    
    template<typename T> 
    struct choose_tag<T, enable_if_t<contains<T, int>>> 
    { using type = int_tag; }; 
    
    template<typename T> 
    struct choose_tag<T, enable_if_t<contains<T, double, float>>> 
    { using type = float_tag; }; 
    

    通用 - print實施

    然後聲明使用這些函數模板:

    ​​

    and call:

    template <class T> 
    class Matrix2D { 
    private: 
        std::vector< std::vector<T> > matrix; 
    public: 
    
        void print() const { 
         print_matrix(detail::tag<T>{}, *this); 
        } 
    }; 
    

    下面是simpletype list版本的實時示例。