Specialize template class for some types

101 Views Asked by At

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

2

There are 2 best solutions below

5
user12002570 On BEST ANSWER

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

2
HolyBlackCat On

In C++20 you can use requires as following. (For earlier language versions, use std::enable_if as explained in the other ansert.)

template <typename T> 
class A {};

template <typename T> requires std::is_fundamental_v<T>
class A<T> {};