#include <iostream>
struct my_abstract_class { virtual int x() = 0; };
struct my_incomplete_class;
template<typename T> struct is_array
{ static const bool value = false; };
template<typename T> struct is_array<T[]>
{ static const bool value = true; };
template<typename T, size_t n> struct is_array<T[n]>
{ static const bool value = true; };
template<typename T> struct is_reference
{ static const bool value = false; };
template<typename T> struct is_reference<T&>
{ static const bool value = true; };
template<typename T> struct is_void
{ static const bool value = false; };
template<> struct is_void<void>
{ static const bool value = true; };
template<> struct is_void<void const>
{ static const bool value = true; };
template<> struct is_void<void volatile>
{ static const bool value = true; };
template<> struct is_void<void const volatile>
{ static const bool value = true; };
template<typename T>
class is_abstract_class_or_function
{
typedef char (&Two)[2];
template<typename U> static char test(U(*)[1]);
template<typename U> static Two test(...);
public:
static const bool value =
!is_reference<T>::value &&
!is_void<T>::value &&
(sizeof(test<T>(0)) == sizeof(Two));
};
template<typename T> struct is_returnable
{ static const bool value = !is_array<T>::value && !is_abstract_class_or_function<T>::value; };
int main()
{
::std::cout
<< is_returnable<int>::value << ::std::endl
<< is_returnable<int[]>::value << ::std::endl
<< is_returnable<int[2]>::value << ::std::endl
<< is_returnable<int()>::value << ::std::endl
<< is_returnable<my_abstract_class>::value << ::std::endl
<< is_returnable<my_incomplete_class>::value << ::std::endl
;
return 0;
}