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

时间:2010-04-28 09:09:39

标签: c++ types

In<现代C ++设计>,它介绍了一种通过引入所谓的类型列表来检查类型基本类型的方法。但是,如果我不想包含这么多的loki代码并且想要一个简单的函数来实现它呢?最简单的方法是什么?

3 个答案:

答案 0 :(得分:5)

不要重新发明轮子使用 boost :: type_traits

http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/index.html

答案 1 :(得分:4)

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

// 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);
}

在此代码中,如果传入intchar等类型,编译器将使用IsFundamentalType的特化(假设您已为所有人定义了特殊化)基本类型)。否则,编译器将使用通用模板,因为NonFundamentalType类就是这种情况。重要的是,专门的成员result成员定义为true,而通用模板也有result成员定义为false。然后,您可以将result成员用于if语句。优化编译器应该能够忽略if语句,看到表达式减少到一个恒定的真/假值,所以做这样的事情不应该施加运行时惩罚。

答案 2 :(得分:2)

最简单的方法是创建一个type-traits对象。基本上,您创建一个对象(让我们称之为is_fundamental&lt; T&gt;),该对象由类型参数化,默认情况下继承自boost :: type_traits :: no_type;然后你在所有基本类型上专门化对象,使该特化继承自boost :: type_traits :: yes_type。那么你可以使用is_fundamental&lt; T&gt; :: value作为布尔值来告诉你类型T是否是基本类型。在大多数情况下,你真的不需要知道一个类型是否是基本的,当你这样做时,它几乎总是涉及模板,无论如何,所以不妨这样做。

我还应该指出,Boost已经定义了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

这基本上就是创建这种类型特征对象所需要的。请注意,人们可以恶意地将类型特征专门化为非基本类型,尽管大多数情况都是如此。

然后,您可以使用上述内容创建更具功能性的内容。例如,使用boost :: type_traits :: is_fundamental类,您可以创建以下内容:

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

由于可以从参数中推导出模板特化,因此可以在不明确指定类型的情况下调用此isFundamental函数。例如,如果你编写isFundamental(5),它将隐式调用isFundamental&lt; int&gt;(5),它将返回true。但请注意,如果您创建此类函数,则不允许您测试void。你可以创建一个没有参数的函数,但是这个类型不会被推导出来,所以它不会比简单地使用boost :: type_traits :: is_fundamenta&lt; T&gt; :: value更漂亮,所以在这种情况下,也可以使用它。