【发布时间】:2010-08-11 13:01:29
【问题描述】:
在一些标准模板函数的描述中,我看到了类似的内容:
如果模板参数是整数类型,那么行为就是这样。
否则就是这样那样。
如何进行类似的测试?也许是dynamic_cast?
由于我编写的函数是供我个人使用的,我可以依靠自己只提供正确的参数,但为什么会错过学习的机会呢? :)
【问题讨论】:
在一些标准模板函数的描述中,我看到了类似的内容:
如果模板参数是整数类型,那么行为就是这样。
否则就是这样那样。
如何进行类似的测试?也许是dynamic_cast?
由于我编写的函数是供我个人使用的,我可以依靠自己只提供正确的参数,但为什么会错过学习的机会呢? :)
【问题讨论】:
除了其他答案之外,应该注意的是,测试可以在运行时使用,也可以在编译时使用,以根据类型是否为整数来选择正确的实现:
运行时版本:
// Include either <boost/type_traits/is_integral.hpp> (if using Boost)
// or <type_traits> (if using c++1x)
// In the following, is_integral shoudl be prefixed by either boost:: or std::
template <typename T>
void algorithm(const T & t)
{
// some code
if (is_integral<T>::value)
{
// operations to perform if T is an integral type
}
else
{
// operations to perform if T is not an integral type
}
// some other code
}
但是,当算法的实现很大程度上取决于测试时,可以改进此解决方案。在这种情况下,我们将测试放在函数的顶部,然后是一个大的then 块和一个大的else 块。在这种情况下,一种常见的方法是重载函数并让编译器使用 SFINAE 选择正确的实现。一个简单的方法是使用boost::enable_if:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
template <typename T>
typename boost::enable_if<boost::is_integral<T> >::type
algorithm(const T & t)
{
// implementation for integral types
}
template <typename T>
typename boost::disable_if<boost::is_integral<T> >::type
algorithm(const T & t)
{
// implementation for non integral types
}
在调用algorithm 函数时,编译器将根据模板参数是否为整数来“选择”正确的实现。
【讨论】:
#include <type_traits>
#include <iostream>
struct trivial
{
int val;
};
int main()
{
std::cout << "is_integral<trivial> == " << std::boolalpha
<< std::is_integral<trivial>::value << std::endl;
std::cout << "is_integral<int> == " << std::boolalpha
<< std::is_integral<int>::value << std::endl;
std::cout << "is_integral<float> == " << std::boolalpha
<< std::is_integral<float>::value << std::endl;
return (0);
}
然后您使用std::is_integral<> 来确定操作。
【讨论】:
如果您无法使用 C++11 功能,std::numeric_limits<T>::is_integer 将 the same thing 用作 std::is_integral<T>::value,并且可用于 C++98。
注意98版本是intger,不是intgral。
【讨论】:
Boost.TypeTraits 提供 is_integral(),如另一个响应中所述,如果您的编译器尚不支持下一个标准的 C++ 功能。
【讨论】: