C++98/03 std::is_constructible implementation

后端 未结 2 1927
南旧
南旧 2020-12-19 02:42

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

2条回答
  •  不思量自难忘°
    2020-12-19 02:55

    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

提交回复
热议问题