
//  (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and   
//  distribute this software is granted provided this copyright notice appears
//  in all copies. This software is provided "as is" without express or implied
//  warranty, and with no claim as to its suitability for any purpose.

#include <boost/type_traits/object_traits.hpp>
#include <boost/utility.hpp>
#include <boost/test/cpp_main.cpp>

#ifdef __BORLANDC__
#pragma hrdstop
#endif
#include "boost/type_traits/type_traits_test.hpp"

NESTED_DECL(is_class)
NESTED_DECL(is_object)
NESTED_DECL(is_scalar)
NESTED_DECL(is_compound)
NESTED_DECL(is_POD)

struct non_default_constructable_UDT
{
   non_default_constructable_UDT(const non_default_constructable_UDT&){}
private:
   non_default_constructable_UDT(){}
};

int cpp_main(int argc, char* argv[])
{
   NESTED_TEST(is_class, int)
   NESTED_TEST(is_class, UDT)
   NESTED_TEST(is_object, int)
   NESTED_TEST(is_object, void)
   NESTED_TEST(is_object, UDT)
   NESTED_TEST(is_scalar, void)
   NESTED_TEST(is_scalar, int)
   NESTED_TEST(is_compound, int)
   NESTED_TEST(is_compound, UDT)
   NESTED_TEST(is_POD, int)
   NESTED_TEST(is_POD, UDT)

   value_test(false, boost::is_class<int>::value)
   value_test(false, boost::is_class<const int>::value)
   value_test(false, boost::is_class<volatile int>::value)
   value_test(false, boost::is_class<int*>::value)
   value_test(false, boost::is_class<int* const>::value)
   value_test(false, boost::is_class<int[2]>::value)
   value_test(false, boost::is_class<int&>::value)
   value_test(false, boost::is_class<mf4>::value)
   value_test(false, boost::is_class<f1>::value)
   value_test(false, boost::is_class<enum_UDT>::value)
   value_test(true, boost::is_class<UDT>::value)
   value_test(true, boost::is_class<UDT const>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(true, boost::is_class<test_abc1>::value)
   value_test(true, boost::is_class<test_abc1 const>::value)
#endif
   value_test(true, boost::is_class<UDT volatile>::value)
   value_test(true, boost::is_class<empty_UDT>::value)
   value_test(true, boost::is_class<std::iostream>::value)
   value_test(false, boost::is_class<UDT*>::value)
   value_test(false, boost::is_class<UDT[2]>::value)
   value_test(false, boost::is_class<UDT&>::value)
   value_test(false, boost::is_class<void>::value)

   value_test(true, boost::is_object<int>::value)
   value_test(true, boost::is_object<UDT>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(true, boost::is_object<test_abc1>::value)
#endif
   value_test(false, boost::is_object<int&>::value)
   value_test(false, boost::is_object<void>::value)

   value_test(true, boost::is_scalar<int>::value)
   value_test(true, boost::is_scalar<void*>::value)
   value_test(false, boost::is_scalar<void>::value)
   value_test(false, boost::is_scalar<UDT>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::is_scalar<test_abc1>::value)
#endif
   value_test(false, boost::is_scalar<int&>::value)

   value_test(true, boost::is_compound<UDT>::value)
   value_test(true, boost::is_compound<void*>::value)
   value_test(false, boost::is_compound<void>::value)
   value_test(false, boost::is_compound<int>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(true, boost::is_compound<test_abc1>::value)
#endif

   value_test(true, boost::is_POD<int>::value)
   value_test(true, boost::is_POD<int*>::value)
   value_test(false, boost::is_POD<int&>::value)
   value_test(true, boost::is_POD<int*const>::value)
   value_test(true, boost::is_POD<const int>::value)
   value_test(true, boost::is_POD<volatile int>::value)
   value_test(false, boost::is_POD<const int&>::value)
   value_test(true, boost::is_POD<int[2]>::value)
   value_test(true, boost::is_POD<int[3][2]>::value)
   value_test(true, boost::is_POD<int[2][4][5][6][3]>::value)
   value_test(true, boost::is_POD<f1>::value)
   value_test(true, boost::is_POD<mf2>::value)
   value_test(false, boost::is_POD<UDT>::value)
   value_test(false, boost::is_POD<empty_UDT>::value)
   value_test(true, boost::is_POD<enum_UDT>::value)
   value_test(true, boost::is_POD<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::is_POD<test_abc1>::value)
#endif

   value_test(true, boost::has_trivial_constructor<int>::value)
   value_test(true, boost::has_trivial_constructor<int*>::value)
   value_test(true, boost::has_trivial_constructor<int*const>::value)
   value_test(true, boost::has_trivial_constructor<const int>::value)
   value_test(true, boost::has_trivial_constructor<volatile int>::value)
   value_test(true, boost::has_trivial_constructor<int[2]>::value)
   value_test(true, boost::has_trivial_constructor<int[3][2]>::value)
   value_test(true, boost::has_trivial_constructor<int[2][4][5][6][3]>::value)
   value_test(true, boost::has_trivial_constructor<f1>::value)
   value_test(true, boost::has_trivial_constructor<mf2>::value)
   value_test(false, boost::has_trivial_constructor<UDT>::value)
   soft_value_test(true, boost::has_trivial_constructor<empty_UDT>::value)
   value_test(true, boost::has_trivial_constructor<enum_UDT>::value)
   value_test(true, boost::has_trivial_constructor<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::has_trivial_constructor<test_abc1>::value)
#endif

   value_test(true, boost::has_trivial_copy<int>::value)
   value_test(true, boost::has_trivial_copy<int*>::value)
   value_test(true, boost::has_trivial_copy<int*const>::value)
   value_test(true, boost::has_trivial_copy<const int>::value)
   // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
   value_test(false, boost::has_trivial_copy<volatile int>::value)
   value_test(true, boost::has_trivial_copy<int[2]>::value)
   value_test(true, boost::has_trivial_copy<int[3][2]>::value)
   value_test(true, boost::has_trivial_copy<int[2][4][5][6][3]>::value)
   value_test(true, boost::has_trivial_copy<f1>::value)
   value_test(true, boost::has_trivial_copy<mf2>::value)
   value_test(false, boost::has_trivial_copy<UDT>::value)
   soft_value_test(true, boost::has_trivial_copy<empty_UDT>::value)
   value_test(true, boost::has_trivial_copy<enum_UDT>::value)
   value_test(true, boost::has_trivial_copy<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::has_trivial_copy<test_abc1>::value)
#endif

   value_test(true, boost::has_trivial_assign<int>::value)
   value_test(true, boost::has_trivial_assign<int*>::value)
   value_test(false, boost::has_trivial_assign<int*const>::value)
   value_test(false, boost::has_trivial_assign<const int>::value)
   // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
   value_test(false, boost::has_trivial_assign<volatile int>::value)
   value_test(true, boost::has_trivial_assign<int[2]>::value)
   value_test(true, boost::has_trivial_assign<int[3][2]>::value)
   value_test(true, boost::has_trivial_assign<int[2][4][5][6][3]>::value)
   value_test(true, boost::has_trivial_assign<f1>::value)
   value_test(true, boost::has_trivial_assign<mf2>::value)
   value_test(false, boost::has_trivial_assign<UDT>::value)
   soft_value_test(true, boost::has_trivial_assign<empty_UDT>::value)
   value_test(true, boost::has_trivial_assign<enum_UDT>::value)
   value_test(true, boost::has_trivial_assign<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::has_trivial_assign<test_abc1>::value)
#endif

   value_test(true, boost::has_trivial_destructor<int>::value)
   value_test(true, boost::has_trivial_destructor<int*>::value)
   value_test(true, boost::has_trivial_destructor<int*const>::value)
   value_test(true, boost::has_trivial_destructor<const int>::value)
   value_test(true, boost::has_trivial_destructor<volatile int>::value)
   value_test(true, boost::has_trivial_destructor<int[2]>::value)
   value_test(true, boost::has_trivial_destructor<int[3][2]>::value)
   value_test(true, boost::has_trivial_destructor<int[2][4][5][6][3]>::value)
   value_test(true, boost::has_trivial_destructor<f1>::value)
   value_test(true, boost::has_trivial_destructor<mf2>::value)
   value_test(false, boost::has_trivial_destructor<UDT>::value)
   value_test(false, boost::has_trivial_destructor<empty_UDT>::value)
   value_test(true, boost::has_trivial_destructor<enum_UDT>::value)
   value_test(true, boost::has_trivial_destructor<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::has_trivial_destructor<test_abc1>::value)
#endif

   value_test(true, boost::has_nothrow_constructor<int>::value)
   value_test(true, boost::has_nothrow_constructor<int*>::value)
   value_test(true, boost::has_nothrow_constructor<int*const>::value)
   value_test(true, boost::has_nothrow_constructor<const int>::value)
   value_test(true, boost::has_nothrow_constructor<volatile int>::value)
   value_test(true, boost::has_nothrow_constructor<int[2]>::value)
   value_test(true, boost::has_nothrow_constructor<int[3][2]>::value)
   value_test(true, boost::has_nothrow_constructor<int[2][4][5][6][3]>::value)
   value_test(true, boost::has_nothrow_constructor<f1>::value)
   value_test(true, boost::has_nothrow_constructor<mf2>::value)
   value_test(false, boost::has_nothrow_constructor<UDT>::value)
   soft_value_test(true, boost::has_nothrow_constructor<empty_UDT>::value)
   value_test(true, boost::has_nothrow_constructor<enum_UDT>::value)
   value_test(true, boost::has_nothrow_constructor<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::has_nothrow_constructor<test_abc1>::value)
#endif

   value_test(true, boost::has_nothrow_copy<int>::value)
   value_test(true, boost::has_nothrow_copy<int*>::value)
   value_test(true, boost::has_nothrow_copy<int*const>::value)
   value_test(true, boost::has_nothrow_copy<const int>::value)
   // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
   value_test(false, boost::has_nothrow_copy<volatile int>::value)
   value_test(true, boost::has_nothrow_copy<int[2]>::value)
   value_test(true, boost::has_nothrow_copy<int[3][2]>::value)
   value_test(true, boost::has_nothrow_copy<int[2][4][5][6][3]>::value)
   value_test(true, boost::has_nothrow_copy<f1>::value)
   value_test(true, boost::has_nothrow_copy<mf2>::value)
   value_test(false, boost::has_nothrow_copy<UDT>::value)
   soft_value_test(true, boost::has_nothrow_copy<empty_UDT>::value)
   value_test(true, boost::has_nothrow_copy<enum_UDT>::value)
   value_test(true, boost::has_nothrow_copy<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::has_nothrow_copy<test_abc1>::value)
#endif

   value_test(true, boost::has_nothrow_assign<int>::value)
   value_test(true, boost::has_nothrow_assign<int*>::value)
   value_test(false, boost::has_nothrow_assign<int*const>::value)
   value_test(false, boost::has_nothrow_assign<const int>::value)
   // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
   value_test(false, boost::has_nothrow_assign<volatile int>::value)
   value_test(true, boost::has_nothrow_assign<int[2]>::value)
   value_test(true, boost::has_nothrow_assign<int[3][2]>::value)
   value_test(true, boost::has_nothrow_assign<int[2][4][5][6][3]>::value)
   value_test(true, boost::has_nothrow_assign<f1>::value)
   value_test(true, boost::has_nothrow_assign<mf2>::value)
   value_test(false, boost::has_nothrow_assign<UDT>::value)
   soft_value_test(true, boost::has_nothrow_assign<empty_UDT>::value)
   value_test(true, boost::has_nothrow_assign<enum_UDT>::value)
   value_test(true, boost::has_nothrow_assign<void>::value)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, boost::has_nothrow_assign<test_abc1>::value)
#endif

   soft_value_test(false, boost::is_empty<int>::value)
   soft_value_test(false, boost::is_empty<int*>::value)
   soft_value_test(false, boost::is_empty<int&>::value)
   soft_value_test(false, boost::is_empty<void>::value)
#if defined(__MWERKS__) && __MWERKS__ < 0x3000 || defined(__HP_aCC)
   // apparent compiler bug causes this to fail to compile:
   value_fail(false, boost::is_empty<int[2]>::value)
#else
   soft_value_test(false, boost::is_empty<int[2]>::value)
#endif
   soft_value_test(false, boost::is_empty<f1>::value)
   soft_value_test(false, boost::is_empty<mf1>::value)
   soft_value_test(false, boost::is_empty<UDT>::value)
   soft_value_test(true, boost::is_empty<empty_UDT>::value)
   soft_value_test(true, boost::is_empty<empty_POD_UDT>::value)
   // this one will not compile on most compilers,
   // because we can't tell the difference between
   // unions and classes:
   value_fail(true, boost::is_empty<empty_union_UDT>::value)
#if defined(__MWERKS__) && __MWERKS__ < 0x3000 || defined(__HP_aCC)
   // apparent compiler bug causes this to fail to compile:
   value_fail(false, boost::is_empty<enum_UDT>::value)
#else
   soft_value_test(false, boost::is_empty<enum_UDT>::value)
#endif
   soft_value_test(true, boost::is_empty<boost::noncopyable>::value)
   soft_value_test(false, boost::is_empty<non_empty>::value)
   soft_value_test(false, boost::is_empty<const non_empty&>::value)
   soft_value_test(true, boost::is_empty<non_default_constructable_UDT>::value)

   value_test(false, (boost::is_base_and_derived<Derived,Base>::value));
   value_test(true, (boost::is_base_and_derived<Derived,Derived>::value));
   value_test(true, (boost::is_base_and_derived<Base,Base>::value));
   value_test(true, (boost::is_base_and_derived<Base,Derived>::value));
   value_test(false, (boost::is_base_and_derived<NonDerived,Base>::value));
   value_test(false, (boost::is_base_and_derived<Base,void>::value));
   value_test(false, (boost::is_base_and_derived<Base,const void>::value));
   value_test(false, (boost::is_base_and_derived<void,Derived>::value));
   value_test(false, (boost::is_base_and_derived<const void,Derived>::value));
   value_test(false, (boost::is_base_and_derived<int, int>::value));
   value_test(false, (boost::is_base_and_derived<const int, int>::value));
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
   value_test(false, (boost::is_base_and_derived<Base&,Derived>::value));
   value_test(false, (boost::is_base_and_derived<Base&,Derived&>::value));
   value_test(false, (boost::is_base_and_derived<Base,Derived&>::value));
   value_test(false, (boost::is_base_and_derived<Base,void>::value));
#endif

   return check_result(argc, argv);
}

//
// define the number of failures expected for given compilers:
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551)
// can't handle enum's or classes that are POD's
unsigned int expected_failures = 9;
#elif defined(__SUNPRO_CC)
#if (__SUNPRO_CC <= 0x520)
unsigned int expected_failures = 55;
#elif (__SUNPRO_CC < 0x530)
unsigned int expected_failures = 25;
#else
unsigned int expected_failures = 0;
#endif
#elif defined(__MWERKS__) && __MWERKS__ < 0x3000
unsigned int expected_failures = 10;
#elif defined(BOOST_MSVC)
unsigned int expected_failures = 0;
#elif defined(__HP_aCC)
unsigned int expected_failures = 2;
#elif defined(__EDG_VERSION__) && __EDG_VERSION__ < 240
unsigned int expected_failures = 3;
#else
unsigned int expected_failures = 0;
#endif


