In<现代C ++设计>,它介绍了一种通过引入所谓的类型列表来检查类型基本类型的方法。但是,如果我不想包含这么多的loki代码并且想要一个简单的函数来实现它呢?最简单的方法是什么?
答案 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);
}
在此代码中,如果传入int
或char
等类型,编译器将使用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更漂亮,所以在这种情况下,也可以使用它。