c++ - C++98/03 std::is_constructible implementation -


the base components of hobby library has work c++98 , c++11 compilers. learn , enjoy myself created c++98 implementations of several type support functionality (like enable_if, conditional, is_same, is_integral etc. ...) in order use them when there no c++11 support.

however while implementing is_constructible got stuck. there kind of template magic (some kind of sfinae) can implement without c++11 support (declval)?

of course there no variadic template support in c++03, specialise implementation till depth. main question if there technique can decide whether t constructible given types or not.

it's possible:

#include <iostream>  template<typename t, t val> struct integral_constant {     typedef integral_constant type;     typedef t value_type;     enum {         value = val     }; };  typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type;  template<typename t> struct remove_ref {     typedef t type; };  template<typename t> struct remove_ref<t&> {     typedef t type; };  // is_base_of https://stackoverflow.com/questions/2910979/how-does-is-base-of-work namespace aux {     typedef char yes[1];     typedef char no[2];      template <typename b, typename d>     struct host     {         operator b*() const;         operator d*();     }; } template <typename b, typename d> struct is_base_of {   template <typename t>    static aux::yes& check(d*, t);   static aux::no& check(b*, int);    static const bool value = sizeof(check(aux::host<b,d>(), int())) == sizeof(aux::yes); };  template<typename t> struct remove_cv {     typedef t type; }; template<typename t> struct remove_cv<const t> {     typedef t type; }; template<typename t> struct remove_cv<volatile t> {     typedef t type; }; template<typename t> struct remove_cv<const volatile t> {     typedef t type; };  template<typename t> struct is_void : integral_constant<bool, false> {}; template<> struct is_void<void> : integral_constant<bool, true> {};  template <bool, typename t, typename> struct conditional {     typedef t type; }; template <typename t, typename u> struct conditional<false, t, u> {     typedef u type; };   namespace aux {  template<typename t, typename u> struct is_more_const : integral_constant<bool, false> {};  template<typename t, typename u> struct is_more_const<const t, u> : integral_constant<bool, true> {};  template<typename t, typename u> struct is_more_const<const t, const u> : integral_constant<bool, false> {};  template<typename t, typename u> struct is_more_volatile : integral_constant<bool, false> {};  template<typename t, typename u> struct is_more_volatile<volatile t, u> : integral_constant<bool, true> {};  template<typename t, typename u> struct is_more_volatile<volatile t, volatile u> : integral_constant<bool, false> {};  template<typename t, typename u> struct is_more_cv : integral_constant<bool, is_more_const<t,u>::value && is_more_volatile<t,u>::value> {};       template<typename t>     struct is_default_constructible {         template<typename u>         static yes& test(int(*)[sizeof(new u)]);         template<typename u>         static no& test(...);         enum {             value = sizeof(test<t>(0)) == sizeof(yes)         };     };          template<typename t, typename arg>     struct is_constructible_1 {         template<typename u, typename arg_>         static yes& test(int(*)[sizeof(u(static_cast<arg_>(*((typename remove_ref<arg_>::type*)0))))]);         template<typename u, typename arg_>         static no& test(...);         enum {             value = sizeof(test<t, arg>(0)) == sizeof(yes)         };     };         // base pointer construct derived pointer     template<typename t, typename u>     struct is_constructible_1<t*, u*>         : conditional<             is_void<typename remove_cv<t>::type>::value,             integral_constant<bool, true>,             typename conditional<                 is_void<typename remove_cv<u>::type>::value,                 integral_constant<bool, false>,                 typename conditional<                     is_more_cv<t, u>::value,                     integral_constant<bool, false>,                     is_base_of<t,u>                 >::type             >::type         >::type     {};      // base pointer construct derived pointer     template<typename t, typename u>     struct is_constructible_1<t&, u&>         : conditional<             is_more_cv<t, u>::value,             integral_constant<bool, false>,             is_base_of<t,u>         >::type     {};       template<typename t, typename arg1, typename arg2>     struct is_constructible_2 {         template<typename u, typename arg1_, typename arg2_>         static yes& test(int(*)[             sizeof(u(                 static_cast<arg1_>(*((typename remove_ref<arg1_>::type*)0)),                 static_cast<arg2_>(*((typename remove_ref<arg2_>::type*)0))                 ))             ]);         template<typename u, typename arg1_, typename arg2_>         static no& test(...);         enum {             value = sizeof(test<t, arg1, arg2>(0)) == sizeof(yes)         };     }; }  template<typename t, typename arg1 = void, typename arg2 = void> struct is_constructible : integral_constant<bool, aux::is_constructible_2<t, arg1, arg2>::value> {  };  template<typename t, typename arg> struct is_constructible<t, arg> : integral_constant<bool, aux::is_constructible_1<t, arg>::value> {  }; template<typename t> struct is_constructible<t> : integral_constant<bool, aux::is_default_constructible<t>::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<foo>::value));     test((is_constructible<bar>::value));     test((is_constructible<foo, int>::value));     test((is_constructible<bar, int>::value));     test((is_constructible<foo, const foo&>::value));     test((is_constructible<bar, bar>::value));     test((is_constructible<bar, int, double>::value));     test((is_constructible<bar, int, double&>::value));     test((is_constructible<bar, int, const double&>::value));     test((is_constructible<int*, void*>::value));     test((is_constructible<void*, int*>::value));     test((is_constructible<base&, derived&>::value));     test((is_constructible<derived*, base*>::value));     // via fuzz     test((is_constructible<bar, fuzz_explicit>::value));     test((is_constructible<bar, fuzz_implicit>::value));     // via buzz     test((is_constructible<bar, buzz_explicit>::value));     test((is_constructible<bar, buzz_implicit>::value));     // integer promotion     test((is_constructible<bar, char>::value));     // integer conversion     test((is_constructible<bar, unsigned long>::value)); } 

you can expand 2 parameters version 3, 4, 5, ... parameters further more.

live demo


this works g++ 4.4.7

it doesn't work g++ 4.3.6


Comments

Popular posts from this blog

java - SSE Emitter : Manage timeouts and complete() -

jquery - uncaught exception: DataTables Editor - remote hosting of code not allowed -

java - How to resolve error - package com.squareup.okhttp3 doesn't exist? -