Reputation: 10911
I want to use SFINAE to stop from explicitly calling the destructor because MSVS 2010 considers it an error when done on a builtin type pointer.
How would I do this?
Upvotes: 0
Views: 245
Reputation: 203
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
Upvotes: 0
Reputation: 56863
You might look at it from the wrong angle: You shouldn't exclude what does not work, you should detect what does work. In your case, you are trying to check if a given type T
is a class and hence you could call the destructor.
That said, you want std::is_class
. If it is not available for your compiler, there is Boost.TypeTraits' boost::is_class
available which works with VC++ 8 and newer.
Upvotes: 2
Reputation: 1683
This shows how to specialize a function so it is called for fundamental data types in 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;
}
Here are the other fundamental tests
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'
Upvotes: 1