我想使用 SFINAE 来停止显式调用析构函数,因为 MSVS 2010 在对内置类型指针执行时认为它是一个错误。
我该怎么做?
您可能会从错误的角度看待它:您不应该排除无效的内容,而应该检测有效的内容。在您的情况下,您正在尝试检查给定类型T
是否是类,因此您可以调用析构函数。
也就是说,你想要std::is_class
. 如果它不适用于您的编译器,则可以使用Boost.TypeTraits'boost::is_class
,它适用于 VC++ 8 和更高版本。
这显示了如何专门化一个函数,以便在 C++ 中为基本数据类型调用它。
template < class T>
void delete_object(T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = 0) {
// Do nothing because this is not an object
}
template<class T>
void delete_object(T* object) {
delete object;
}
int main()
{
int arithmetic1 = 1;
delete_object(arithmetic1);
float arithmetic2 = 1;
delete_object(arithmetic2);
Object* object1 = new Object();
delete_object(object1);
return 0;
}
这是其他基本测试
std::is_integral<> - 'char' up to 'long long'
std::is_floating_point - 'float' up to 'long double'
std::is_signed<> - signed types
std::is_unsigned<> - unsigned types
std::is_arithmetic - is_integral<> OR is_floating_point<>
std::is_fundamental<> - is_arithmetic<> OR 'void'
With the following type function we can determine whether a type is a class type:
// traits/isclasst.hpp
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
template<typename C> static Two test(…);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
This template uses SFINAME principle.
The following program uses this type function to test whether certain types and objects are class types:
// traits/isclasst.cpp
#include <iostream>
#include "isclasst.hpp"
class MyClass {
};
struct MyStruct {
};
union MyUnion {
};
void myfunc()
{
}
enumE{e1}e;
// check by passing type as template argument
template <typename T>
void check()
{
if (IsClassT<T>::Yes) {
std::cout << " IsClassT " << std::endl;
}
else {
std::cout << " !IsClassT " << std::endl;
}
}
// check by passing type as function call argument
template <typename T>
void checkT (T)
{
check<T>();
}
int main()
{
std::cout << "int: ";
check<int>();
std::cout << "MyClass: ";
check<MyClass>();
std::cout << "MyStruct:";
MyStruct s;
checkT(s);
std::cout << "MyUnion: ";
check<MyUnion>();
std::cout << "enum: ";
checkT(e);
std::cout << "myfunc():";
checkT(myfunc);
}
The program has the following output:
int: !IsClassT
MyClass: IsClassT
MyStruct: IsClassT
MyUnion: IsClassT
enum: !IsClassT
myfunc(): !IsClassT