Identifying primitive types in templates

后端 未结 8 810
南旧
南旧 2020-11-27 17:40

I am looking for a way to identify primitives types in a template class definition.

I mean, having this class :

template
class A{
void         


        
相关标签:
8条回答
  • 2020-11-27 18:25

    It cannot be done exactly the way you asked. Here is how it can be done :

    template<class T>
    class A{
    void doWork(){
       bool isPrimitive = boost::is_fundamental<T>::value;
       if(isPrimitive)
         doSomething();
       else
         doSomethingElse(); 
    }
    private:
    T *t; 
    };
    

    You may get a warning if you put the value of isPrimitive directly inside the if statement. This is why i introduced a temporary variable.

    0 讨论(0)
  • 2020-11-27 18:27

    Yet another similar examples:

    #include  <boost/type_traits/is_fundamental.hpp>
    #include <iostream>
    
    template<typename T, bool=true>
    struct foo_impl
    {
        void do_work()
        {
            std::cout << "0" << std::endl;
        }
    };
    template<typename T>
    struct foo_impl<T,false>
    {
        void do_work()
        {
            std::cout << "1" << std::endl;
        }
    };
    
    template<class T>
    struct foo
    {
        void do_work()
        {
            foo_impl<T, boost::is_fundamental<T>::value>().do_work();
        }
    };
    
    
    int main()
    {
        foo<int> a; a.do_work();
        foo<std::string> b; b.do_work();
    }
    
    0 讨论(0)
  • 2020-11-27 18:29

    Boost TypeTraits has plenty of stuff.

    0 讨论(0)
  • 2020-11-27 18:29

    Assuming by 'Primitive Type' you mean the built in types you can do a series of template specializations. Your code would become:

    template<class T>
    struct A{
        void doWork();
    private:
        T *t; 
    };
    
    template<> void A<float>::doWork()
    {
        doSomething();
    }
    
    template<> void A<int>::doWork()
    {
        doSomething();
    }
    
    // etc. for whatever types you like
    
    template<class T> void A<T>::doWork()
    {
        doSomethingElse();
    }
    
    0 讨论(0)
  • 2020-11-27 18:34

    There is a better way - using SFINAE. With SFINAE you don't have to list out every primitive type. SFINAE is a technique that depends on the idea that when template specialization fails it falls back to a more general template. ( it stands for "Specialization failure is not an error" ).

    Also you don't really define if you consider a pointer to be a primitive type, so I'll make you templates for all the combinations.

    // takes a pointer type and returns the base type for the pointer.
    // Non-pointer types evaluate to void.
    template < typename T > struct DePtr                       { typedef void R; }; 
    template < typename T > struct DePtr< T * >                { typedef T R; };
    template < typename T > struct DePtr< T * const >          { typedef T R; };
    template < typename T > struct DePtr< T * volatile >       { typedef T R; };
    template < typename T > struct DePtr< T * const volatile > { typedef T R; };
    
    // ::value == true if T is a pointer type
    template < class T > struct IsPointer                        { enum { value = false }; };
    template < class T > struct IsPointer < T *                > { enum { value = true };  };
    template < class T > struct IsPointer < T * const          > { enum { value = true };  };
    template < class T > struct IsPointer < T * volatile       > { enum { value = true };  };
    template < class T > struct IsPointer < T * const volatile > { enum { value = true };  };
    
    // ::value == true if T is a class type. ( class pointer == false )
    template < class T > struct IsClass 
    {
       typedef u8 yes; typedef u16 no; 
       template < class C >    static yes isClass( int C::* );
       template < typename C > static no  isClass( ... );
       enum { value = sizeof( isClass<T>( 0 )) == sizeof( yes ) };
    };
    
    // ::value == true if T* is a class type. ( class == false )
    template < class T > struct IsClassPtr 
    {
       typedef u8 yes; typedef u16 no; 
       template < class C >    static yes isClass( int C::* );
       template < typename C > static no  isClass( ... );
       enum { value = sizeof( isClass< typename DePtr< T >::R >( 0 )) == sizeof( yes ) };
    };
    
    // ::value == true if T is a class or any pointer type - including class and non-class pointers.
    template < class T > struct IsClassOrPtr : public IsClass<T> { };
    template < class T > struct IsClassOrPtr < T *                > { enum { value = true };  };
    template < class T > struct IsClassOrPtr < T * const          > { enum { value = true };  };
    template < class T > struct IsClassOrPtr < T * volatile       > { enum { value = true };  };
    template < class T > struct IsClassOrPtr < T * const volatile > { enum { value = true };  };
    
    
    template < class T > struct IsClassOrClassPtr : public IsClass<T> { };
    template < class T > struct IsClassOrClassPtr < T *                > : public IsClassPtr< T*                > { };
    template < class T > struct IsClassOrClassPtr < T * const          > : public IsClassPtr< T* const          > { };
    template < class T > struct IsClassOrClassPtr < T * volatile       > : public IsClassPtr< T* volatile       > { };
    template < class T > struct IsClassOrClassPtr < T * const volatile > : public IsClassPtr< T* const volatile > { };
    
    0 讨论(0)
  • 2020-11-27 18:35

    I guess this can do the job quite nicely, without multiple specializations:

    # include <iostream>
    # include <type_traits>
    
    template <class T>
    inline bool isPrimitiveType(const T& data) {
        return std::is_fundamental<T>::value;
    }
    
    struct Foo {
        int x;
        char y;
        unsigned long long z;
    };
    
    
    int main() {
    
        Foo data;
    
        std::cout << "isPrimitiveType(Foo): " << std::boolalpha
            << isPrimitiveType(data) << std::endl;
        std::cout << "isPrimitiveType(int): " << std::boolalpha
            << isPrimitiveType(data.x) << std::endl;
        std::cout << "isPrimitiveType(char): " << std::boolalpha
            << isPrimitiveType(data.y) << std::endl;
        std::cout << "isPrimitiveType(unsigned long long): " << std::boolalpha
            << isPrimitiveType(data.z) << std::endl;
    
    }
    

    And the output is:

    isPrimitiveType(Foo): false  
    isPrimitiveType(int): true  
    isPrimitiveType(char): true  
    isPrimitiveType(unsigned long long): true
    
    0 讨论(0)
提交回复
热议问题