代码之家  ›  专栏  ›  技术社区  ›  Baiyan Huang

有没有一个简单的方法来检查一个基本类型

  •  2
  • Baiyan Huang  · 技术社区  · 15 年前

    在<现代C++设计与开发;它引入了一种通过引入所谓的类型列表来检查类型是否是基本类型的方法。但如果我不想包含这么多loki代码,只想用一个简单的函数来实现它呢?最简单的方法是什么?

    3 回复  |  直到 15 年前
        1
  •  4
  •   In silico    15 年前

    您可以使用模板专门化来获得所需的内容。

    // General template
    template<typename T>
    struct IsFundamentalType { enum { result = false }; };
    
    // Template specializations for each fundamental type
    template<>
    struct IsFundamentalType<char> { enum { result = true }; };
    
    template<>
    struct IsFundamentalType<int> { enum { result = true }; };
    
    template<>
    struct IsFundamentalType<short> { enum { result = true }; };
    
    template<>
    struct IsFundamentalType<float> { enum { result = true }; };
    
    // And so on for other fundamental types ...
    
    class NonFundamentalType
    {
    };
    
    template<typename T>
    void DoSomething(const T& var)
    {
        if(IsFundamentalType<T>::result)
        {
            printf("I'm fundamental type!\n");
        }
        else
        {
            printf("I'm not a fundamental type!\n");
        }
    }
    
    int main()
    {
        int i = 42;
        char c = 42;
        short s = 42;
        float f = 42.0f;
        NonFundamentalType nft;
        DoSomething(i);
        DoSomething(c);
        DoSomething(s);
        DoSomething(f);
        DoSomething(nft);
    }
    

    在这段代码中,如果传入 int char IsFundamentalType (假设您已经为所有基本类型定义了专门化)。否则,编译器将使用通用模板,就像 NonFundamentalType result 成员定义为 true 结果 成员定义为 false . 然后你可以使用 委员会成员 if 如果 语句看到表达式减少到一个常量真/假值,所以这样做不应该造成运行时惩罚。

        2
  •  5
  •   mt_serg    15 年前
        3
  •  2
  •   Michael Aaron Safyan    15 年前

    最简单的方法是创建一个类型traits对象。基本上,您可以创建一个对象(我们称之为基本对象<T>)由类型参数化并默认从boost::type\u traits::no\u type继承的;然后在所有基本类型上专门化对象,使专门化从boost::type\u traits::yes\u type继承。因此,您可以使用is\u basic<T>::值作为布尔值,它将告诉您类型T是否为基本类型。在大多数情况下,你真的不需要知道一个类型是否是基本的,当你知道的时候,它几乎总是涉及模板,无论如何,所以不妨这样做。

    boost::type_traits::is_fundamental 这正是你想要的。你可以看到 is_fundamental.hpp 他们用他们的其他类型特征来定义它;如果一个类型是内置的算术类型,或者是“void”类型(也被认为是基本类型),那么它就是基本类型。试图从Boost中找出一些问题可能会让人困惑,但简单的做法是:

    template<typename T, T VAL> struct constant_value
    {
        static const T value = VAL;
    };
    
    typedef constant_value<bool,true> yes_type;
    typedef constant_value<bool,false> no_type;
    
    template<typename T> struct is_fundamental : public no_type{};
    
    // Create a macro for convenience
    #define DECLARE_FUNDAMENTAL(X) \
         template<> struct is_fundamental<X> : public yes_type{}
    
    // Specialize for all fundamental types
    DECLARE_FUNDAMENTAL(void);
    DECLARE_FUNDAMENTAL(bool);
    DECLARE_FUNDAMENTAL(signed char);
    DECLARE_FUNDAMENTAL(unsigned char);
    // ... lots more similar specializations ...
    DECLARE_FUNDAMENTAL(wchar_t);
    DECLARE_FUNDAMENTAL(float);
    DECLARE_FUNDAMENTAL(double);
    DECLARE_FUNDAMENTAL(long double);
    
    // Prevent this macro from polluting everything else...
    #undef DECLARE_FUNDAMENTAL
    

    这基本上就是创建这样一个类型traits对象所需要的。请注意,对于非基本类型,可以恶意地将类型特性专门化为true,尽管无论如何,大多数情况都是这样。

    然后你可以使用上面的方法来创建一个更具功能性的东西。例如,使用boost::type\u traits::is\u basic类,可以创建以下内容:

    template<typename T> 
    bool isFundametal(const T&)
    {
        return boost::type_traits::is_fundamental<T>::value;
    }