The base components of my hobby library has to work with C++98 and C++11 compilers. To learn and to enjoy myself I created the C++98 implementations of several type support
It's possible:
#include
template
struct integral_constant {
typedef integral_constant type;
typedef T value_type;
enum {
value = Val
};
};
typedef integral_constant true_type;
typedef integral_constant false_type;
template
struct remove_ref {
typedef T type;
};
template
struct remove_ref {
typedef T type;
};
// is_base_of from https://stackoverflow.com/questions/2910979/how-does-is-base-of-work
namespace aux {
typedef char yes[1];
typedef char no[2];
template
struct Host
{
operator B*() const;
operator D*();
};
}
template
struct is_base_of
{
template
static aux::yes& check(D*, T);
static aux::no& check(B*, int);
static const bool value = sizeof(check(aux::Host(), int())) == sizeof(aux::yes);
};
template
struct remove_cv {
typedef T type;
};
template
struct remove_cv {
typedef T type;
};
template
struct remove_cv {
typedef T type;
};
template
struct remove_cv {
typedef T type;
};
template
struct is_void : integral_constant {};
template<>
struct is_void : integral_constant {};
template
struct type_identity {
// Used to work around Visual C++ 2008's spurious error: "a function-style conversion to a built-in type can only take one argument"
typedef T type;
};
template
struct conditional {
typedef T type;
};
template
struct conditional {
typedef U type;
};
namespace aux {
template
struct is_more_const : integral_constant {};
template
struct is_more_const : integral_constant {};
template
struct is_more_const : integral_constant {};
template
struct is_more_volatile : integral_constant {};
template
struct is_more_volatile : integral_constant {};
template
struct is_more_volatile : integral_constant {};
template
struct is_more_cv : integral_constant::value && is_more_volatile::value> {};
template
struct is_default_constructible {
template
static yes& test(int(*)[sizeof(new U)]);
template
static no& test(...);
enum {
value = sizeof(test(0)) == sizeof(yes)
};
};
template
struct is_constructible_1 {
template
static yes& test(int(*)[sizeof(typename type_identity::type(static_cast(*((typename remove_ref::type*)0))))]);
template
static no& test(...);
enum {
value = sizeof(test(0)) == sizeof(yes)
};
};
// Base pointer construct from Derived Pointer
template
struct is_constructible_1
: conditional<
is_void::type>::value,
integral_constant,
typename conditional<
is_void::type>::value,
integral_constant,
typename conditional<
is_more_cv::value,
integral_constant,
is_base_of
>::type
>::type
>::type
{};
// Base pointer construct from Derived Pointer
template
struct is_constructible_1
: conditional<
is_more_cv::value,
integral_constant,
is_base_of
>::type
{};
template
struct is_constructible_2 {
template
static yes& test(int(*)[
sizeof(typename type_identity::type(
static_cast(*((typename remove_ref::type*)0)),
static_cast(*((typename remove_ref::type*)0))
))
]);
template
static no& test(...);
enum {
value = sizeof(test(0)) == sizeof(yes)
};
};
}
template
struct is_constructible : integral_constant::value> {
};
template
struct is_constructible : integral_constant::value> {
};
template
struct is_constructible : integral_constant::value> {
};
struct Foo {};
struct fuzz_explicit {};
struct fuzz_implicit {};
struct Fuzz {
explicit Fuzz(fuzz_explicit);
Fuzz(fuzz_implicit);
};
struct buzz_explicit {};
struct buzz_implicit {};
struct Buzz {
explicit Buzz(buzz_explicit);
Buzz(buzz_implicit);
};
struct Bar {
Bar(int);
Bar(int, double&);
Bar(Fuzz);
explicit Bar(Buzz);
};
struct Base {};
struct Derived : Base {};
#define TEST(X) std::cout << #X << X << '\n'
int main() {
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible::value));
TEST((is_constructible ::value));
TEST((is_constructible::value));
// via Fuzz
TEST((is_constructible::value));
TEST((is_constructible::value));
// via Buzz
TEST((is_constructible::value));
TEST((is_constructible::value));
// integer promotion
TEST((is_constructible::value));
// integer conversion
TEST((is_constructible::value));
}
You can expand the 2 parameters version for 3, 4, 5, ... parameters further more.
Live Demo
This works with g++ 4.4.7
It doesn't work with g++ 4.3.6