blob: 6e4589cabeade3926d44ee96da95ded4970060a0 [file] [log] [blame]
// -*- C++ -*-
/***************************************************************************
*
* 20.meta.rel.cpp - test exercising meta.rel
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1999-2008 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <type_traits>
#include <rw_driver.h>
#include <rw/_defs.h>
// compile out all test code if extensions disabled
#ifndef _RWSTD_NO_EXT_CXX_0X
/**************************************************************************/
enum enum_A { E_a = 0 };
enum enum_B { E_b = 0 };
struct struct_A {
int i_; float f_;
};
struct struct_AA {
int i_; float f_;
};
class class_B {
int i_; float f_;
};
class class_BB {
int i_; float f_;
};
struct convertible_to_A
{
operator struct_A ();
};
struct constructible_from_B
{
constructible_from_B (class_B);
};
template <class T>
struct derived_t : T
{
};
template <class T>
struct derived_private_t : private T
{
};
template <class T>
struct derived_protected_t : protected T
{
};
template <class T>
struct derived_with_conversion_t : T
{
derived_with_conversion_t (const T&);
};
class incomplete_t;
union union_C {
int i_; float f_;
};
union union_CC {
int i_; float f_;
};
/**************************************************************************/
void test_trait (int line, bool value, bool expect,
const char* trait, const char* typeT, const char* typeU)
{
rw_assert (value == expect, 0, line,
"%s<%s, %s>::type is%{?}n't%{;} %b as expected",
trait, typeT, typeU, value != expect, expect);
}
#define TEST(Trait,TypeT,TypeU,Expect) \
{ const bool value = Trait< TypeT, TypeU >::value; \
test_trait (__LINE__, value, Expect, #Trait, #TypeT, #TypeU); \
} typedef void __dummy
static void test_is_same ()
{
TEST (std::is_same, bool, bool, true);
TEST (std::is_same, char, char, true);
TEST (std::is_same, short, short, true);
TEST (std::is_same, int, int, true);
TEST (std::is_same, long, long, true);
TEST (std::is_same, float, float, true);
TEST (std::is_same, double, double, true);
TEST (std::is_same, enum_A, enum_A, true);
TEST (std::is_same, enum_B, enum_B, true);
TEST (std::is_same, struct_A, struct_A, true);
typedef derived_t<struct_A> derived_A;
TEST (std::is_same, derived_A, derived_A, true);
TEST (std::is_same, class_B, class_B, true);
typedef derived_t<class_B> derived_B;
TEST (std::is_same, derived_B, derived_B, true);
// other combinations should fail
TEST (std::is_same, signed char, char, false);
TEST (std::is_same, char, signed char, false);
TEST (std::is_same, unsigned char, char, false);
TEST (std::is_same, char, unsigned char, false);
TEST (std::is_same, signed char, unsigned char, false);
TEST (std::is_same, unsigned char, signed char, false);
TEST (std::is_same, signed short, unsigned short, false);
TEST (std::is_same, unsigned short, signed short, false);
TEST (std::is_same, signed int, unsigned int, false);
TEST (std::is_same, unsigned int, signed int, false);
TEST (std::is_same, signed long, unsigned long, false);
TEST (std::is_same, unsigned long, signed long, false);
TEST (std::is_same, long, const long, false);
TEST (std::is_same, const long, long, false);
TEST (std::is_same, long, volatile long, false);
TEST (std::is_same, volatile long, long, false);
TEST (std::is_same, long, const volatile long, false);
TEST (std::is_same, const volatile long, long, false);
TEST (std::is_same, enum_A, char, false);
TEST (std::is_same, enum_A, short, false);
TEST (std::is_same, enum_A, int, false);
TEST (std::is_same, enum_A, long, false);
TEST (std::is_same, enum_A, unsigned char, false);
TEST (std::is_same, enum_A, unsigned short, false);
TEST (std::is_same, enum_A, unsigned int, false);
TEST (std::is_same, enum_A, unsigned long, false);
TEST (std::is_same, struct_A, derived_t<struct_A>, false);
TEST (std::is_same, class_B, derived_t<class_B>, false);
TEST (std::is_same, int[], int*, false);
TEST (std::is_same, int*, int[], false);
}
#define TEST(Trait,TypeT,TypeU,Expect) \
{ const bool value = Trait< TypeT, TypeU >::value; \
test_trait (__LINE__, value, Expect, #Trait, #TypeT, #TypeU); \
} typedef void __dummy
static void test_is_base_of ()
{
TEST (std::is_base_of, bool, bool, false);
TEST (std::is_base_of, char, char, false);
TEST (std::is_base_of, short, short, false);
TEST (std::is_base_of, int, int, false);
TEST (std::is_base_of, long, long, false);
TEST (std::is_base_of, float, float, false);
TEST (std::is_base_of, double, double, false);
TEST (std::is_base_of, enum_A, enum_A, false);
TEST (std::is_base_of, enum_B, enum_B, false);
TEST (std::is_base_of, struct_A, struct_A, true);
TEST (std::is_base_of, derived_t<struct_A>,
derived_t<struct_A>, true);
TEST (std::is_base_of, class_B, class_B, true);
TEST (std::is_base_of, derived_t<class_B>,
derived_t<class_B>, true);
#if defined (_RWSTD_TT_IS_BASE_OF) \
|| defined (_RWSTD_TT_IS_CLASS) \
|| defined (_RWSTD_TT_IS_UNION)
// without one of the above, we can't reliably implement
// this trait for union type
TEST (std::is_base_of, union_C, union_C, false);
#else
rw_warn (0, 0, __LINE__,
"portions of test_is_base_of() have been disabled due "
"to lack of compiler support.");
#endif
// public inheritance
TEST (std::is_base_of, struct_A, derived_t<struct_A>, true);
TEST (std::is_base_of, class_B, derived_t<class_B>, true);
#if defined (__SUNPRO_CC) && (__SUNPRO_CC <= 0x590)
// for some reason the trick used to detect private and protected
// inheritance doesn't work on sunpro-5.9
rw_warn (0, 0, __LINE__,
"unable to detect private or protected base classes.");
#else
// protected inheritance
TEST (std::is_base_of, struct_A, derived_protected_t<struct_A>, true);
// private inheritance
TEST (std::is_base_of, struct_A, derived_private_t<struct_A>, true);
#endif
// cv-qualified
TEST (std::is_base_of, const struct_A, struct_A, true);
TEST (std::is_base_of, struct_A, const struct_A, true);
TEST (std::is_base_of, volatile struct_A, struct_A, true);
TEST (std::is_base_of, struct_A, volatile struct_A, true);
TEST (std::is_base_of, const volatile struct_A, struct_A, true);
TEST (std::is_base_of, struct_A, const volatile struct_A, true);
TEST (std::is_base_of, const struct_A, derived_t<struct_A>, true);
TEST (std::is_base_of, struct_A, const derived_t<struct_A>, true);
TEST (std::is_base_of, volatile struct_A, derived_t<struct_A>, true);
TEST (std::is_base_of, struct_A, volatile derived_t<struct_A>, true);
TEST (std::is_base_of, const volatile struct_A, derived_t<struct_A>, true);
TEST (std::is_base_of, struct_A, const volatile derived_t<struct_A>, true);
// other combinations should fail
TEST (std::is_base_of, signed char, char, false);
TEST (std::is_base_of, char, signed char, false);
TEST (std::is_base_of, unsigned char, char, false);
TEST (std::is_base_of, char, unsigned char, false);
TEST (std::is_base_of, signed char, unsigned char, false);
TEST (std::is_base_of, unsigned char, signed char, false);
TEST (std::is_base_of, signed short, unsigned short, false);
TEST (std::is_base_of, unsigned short, signed short, false);
TEST (std::is_base_of, signed int, unsigned int, false);
TEST (std::is_base_of, unsigned int, signed int, false);
TEST (std::is_base_of, signed long, unsigned long, false);
TEST (std::is_base_of, unsigned long, signed long, false);
TEST (std::is_base_of, enum_A, char, false);
TEST (std::is_base_of, enum_A, short, false);
TEST (std::is_base_of, enum_A, int, false);
TEST (std::is_base_of, enum_A, long, false);
TEST (std::is_base_of, enum_A, unsigned char, false);
TEST (std::is_base_of, enum_A, unsigned short, false);
TEST (std::is_base_of, enum_A, unsigned int, false);
TEST (std::is_base_of, enum_A, unsigned long, false);
TEST (std::is_base_of, int[], int*, false);
TEST (std::is_base_of, int*, int[], false);
TEST (std::is_base_of, struct_A, class_B, false);
TEST (std::is_base_of, class_B, struct_A, false);
TEST (std::is_base_of, derived_t<struct_A>, struct_A, false);
TEST (std::is_base_of, derived_t<class_B>, class_B, false);
}
static void test_is_convertible ()
{
TEST (std::is_convertible, derived_t<struct_A> , struct_A , true); // slice
TEST (std::is_convertible, derived_t<struct_A>*, struct_A*, true);
TEST (std::is_convertible, derived_t<struct_A>&, struct_A&, true);
TEST (std::is_convertible, derived_t<class_B> , class_B , true); // slice
TEST (std::is_convertible, derived_t<class_B>*, class_B*, true);
TEST (std::is_convertible, derived_t<class_B>&, class_B&, true);
TEST (std::is_convertible, convertible_to_A, struct_A, true);
TEST (std::is_convertible, struct_A, convertible_to_A, false);
TEST (std::is_convertible, convertible_to_A*, struct_A*, false);
TEST (std::is_convertible, convertible_to_A&, struct_A&, false);
TEST (std::is_convertible, constructible_from_B, class_B, false);
TEST (std::is_convertible, class_B, constructible_from_B, true);
TEST (std::is_convertible, class_B*, constructible_from_B*, false);
TEST (std::is_convertible, class_B&, constructible_from_B&, false);
//
// pointer to pointer conversions
//
TEST (std::is_convertible, int*, int*, true);
TEST (std::is_convertible, const int*, const int*, true);
TEST (std::is_convertible, volatile int*, volatile int*, true);
TEST (std::is_convertible, const volatile int*, const volatile int*, true);
// add cv-qualifiers
TEST (std::is_convertible, int*, const int*, true);
TEST (std::is_convertible, int*, volatile int*, true);
TEST (std::is_convertible, int*, const volatile int*, true);
// strip cv-qualifiers
TEST (std::is_convertible, const int*, int*, false);
TEST (std::is_convertible, volatile int*, int*, false);
TEST (std::is_convertible, const volatile int*, int*, false);
//
// special case void conversions
//
TEST (std::is_convertible, void, void, true);
TEST (std::is_convertible, void, long, false);
TEST (std::is_convertible, long, void, false);
//
// array to pointer conversions
//
TEST (std::is_convertible, int[], int*, true);
TEST (std::is_convertible, const int[], const int*, true);
TEST (std::is_convertible, volatile int[], volatile int*, true);
TEST (std::is_convertible, const volatile int[], const volatile int*, true);
// add cv-qualifiers
TEST (std::is_convertible, int[], const int*, true);
TEST (std::is_convertible, int[], volatile int*, true);
TEST (std::is_convertible, int[], const volatile int*, true);
// strip cv-qualifiers
TEST (std::is_convertible, const int[], int*, false);
TEST (std::is_convertible, volatile int[], int*, false);
TEST (std::is_convertible, const volatile int[], int*, false);
//
// pointer to array conversions should all fail
//
TEST (std::is_convertible, int*, int[], false);
TEST (std::is_convertible, const int*, const int[], false);
TEST (std::is_convertible, volatile int*, volatile int[], false);
TEST (std::is_convertible, const volatile int*, const volatile int[], false);
// add cv-qualifiers
TEST (std::is_convertible, int*, const int[], false);
TEST (std::is_convertible, int*, volatile int[], false);
TEST (std::is_convertible, int*, const volatile int[], false);
// strip cv-qualifiers
TEST (std::is_convertible, const int*, int[], false);
TEST (std::is_convertible, volatile int*, int[], false);
TEST (std::is_convertible, const volatile int*, int[], false);
//// from an abstract type is allowed
//TEST (std::is_convertible, abstract_, int, false);
//TEST (std::is_convertible, derived_t<abstract_>, abstract_, false);
TEST (std::is_convertible, long*, void*, true);
TEST (std::is_convertible, void*, long*, false);
// function to function conversions fail
TEST (std::is_convertible, int (), int (), false);
TEST (std::is_convertible, int (), int (char, long), false);
// function to function pointer
TEST (std::is_convertible, int (), int (*)(), true);
TEST (std::is_convertible, int (char, long), int (*)(char, long), true);
TEST (std::is_convertible, int (), int (*)(char), false);
// function to function reference
TEST (std::is_convertible, int (), int (&)(), true);
TEST (std::is_convertible, int (char, long), int (&)(char, long), true);
TEST (std::is_convertible, int (), int (&)(char), false);
TEST (std::is_convertible, int*, void*, true);
#if defined (_MSC_VER) || defined (__IBMCPP__)
// microsoft language extension allows this conversion, and that
// extension is enabled by default.
TEST (std::is_convertible, int (*)(), void*, true);
#else
TEST (std::is_convertible, int (*)(), void*, false);
#endif
TEST (std::is_convertible,
int (*)(derived_t<struct_A>*),
int (*)(struct_A*), false);
TEST (std::is_convertible,
int (*)(struct_A*),
int (*)(derived_t<struct_A>*), false);
// pointer to derived member convertible to
// pointer to base member
TEST (std::is_convertible,
int derived_t<struct_A>::*,
int struct_A::*, false);
// pointer to base member convertible to
// pointer to derived member
TEST (std::is_convertible,
int struct_A::*,
int derived_t<struct_A>::*, true);
TEST (std::is_convertible, int, double, true);
TEST (std::is_convertible, const int, double, true);
}
/**************************************************************************/
static int run_test (int, char*[])
{
test_is_same ();
test_is_base_of ();
test_is_convertible ();
return 0;
}
/**************************************************************************/
#else // _RWSTD_NO_EXT_CXX_0X
/**************************************************************************/
static int run_test (int, char*[])
{
rw_warn (0, 0, __LINE__,
"test disabled because _RWSTD_NO_EXT_CXX_0X is defined");
return 0;
}
#endif // !_RWSTD_NO_EXT_CXX_0X
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"meta.rel",
0 /* no comment */,
run_test,
0);
}