c++c++11templatesmetaprogrammingtemplate-specialization

Specialize template class for some types


How to make a template specialization for trivial types using is_trivial? At the same time, pointers are also trivial, but a separate specialization should remain for them. i am using c++11.

#include <string>
#include <iostream>
#include <type_traits>
#include <vector>
#define Work(var)     A<decltype(var)>().print(&var);

//Base class
class ABase{
    public:
    virtual void print(void* ptr)=0;
};
//default template
template <class T> 
class A : public ABase{
    public:
    void print(void* ptr) override {
        std::cout<<"default "<<ptr<<" size:"<<sizeof(T)<<std::endl;
    }
};
// template for pointers
template <class T> 
class A<T*> : public ABase{
    public:
    void print(void* ptr) override {
        std::cout<<"pointer "<<ptr<<" content:"<<std::endl;
        T* val=static_cast<T*>(ptr);
        Work(*val);
    }
};
// template for arrays
template <class T, std::size_t N> 
class A<T[N]> : public ABase{
    public:
    void print(void* ptr) override {
        std::cout<<"array "<<ptr<<" size:"<<sizeof(T[N])<<" count:"<<N<<std::endl;
    }
};
// template for is_trivial    HOW?
template <> 
class A<int>: public ABase{  // MUST BE FOR ALL TYPES using std::is_trivial<T>::value
    typedef int T;
    public:
    void print(void* ptr) override {
        char* d= static_cast<char*>(ptr);
        std::cout<<"trivial "<<ptr<<" size:"<<sizeof(T)<<" dump:";
        for(int i=0; i<sizeof(T); i++)
            std::cout<<std::hex<<d[i];
        std::cout<<std::endl;
    }
};

int main(){
    int x=10;
    Work(x);
    char c[5]="qwe";
    Work(c);
    char* str= &c[1];
    Work(str);   
}

I saw how this is done for functions, but there was a template data type in the function header and it simplified everything


Solution

  • Since you want C++11 specific solution, you can use std::is_fundamental, std::enable_if as shown below. Note that a second type parameter with a default has been added into the primary template for this to work:

    //-----------------vvvvvvvvvvvvvvvv--------->added second parameter with default
    template <class T, typename = void> 
    class A : public ABase{
        public:
        void print(void* ptr) override {
            std::cout<<"default "<<ptr<<" size:"<<sizeof(T)<<std::endl;
        }
    };
    //specialization for fundamental types
    template <typename C> 
    class A<C, typename std::enable_if<std::is_fundamental<C>::value>::type>: public ABase{  
        
    };
    

    Working demo