Compile time type determination in C++

后端 未结 6 1838
囚心锁ツ
囚心锁ツ 2021-02-01 22:26

A coworker recently showed me some code that he found online. It appears to allow compile time determination of whether a type has an \"is a\" relationship with another type. I

相关标签:
6条回答
  • 2021-02-01 23:01

    It declares two overloaded functions named test, one taking a Base and one taking anything (...), and returning different types.

    It then calls the function with a Derived and checks the size of its return type to see which overload is called. (It actually calls the function with the return value of a function that returns Derived, to avoid using memory)

    Because enums are compile-time constants, all of this is done within the type system at compile-time. Since the functions don't end up getting called at runtime, it doesn't matter that they have no bodies.

    0 讨论(0)
  • 2021-02-01 23:03

    I'm no C++ expert, but it looks to me like the point is to get the compiler to decide between the two overloads of test(). If Derived is derived from Base then the first one will be used, which returns char, otherwise the second one will be used - which returns char[2]. The sizeof() operator then determines which of these happened and sets the value of conversion::exists accordingly.

    0 讨论(0)
  • 2021-02-01 23:05

    The original code will construct an object of Derived, it may brings unexpected result. Below work may be an alternative choice:

    template<typename BaseT, typename CheckT>
    inline  bool    isDerived(const CheckT &t){
        char    test(const BaseT   *t);
        char    (&test(...))[2];
        return  (sizeof(test(&t)) == sizeof(char) );
    }
    
    0 讨论(0)
  • 2021-02-01 23:13

    It's pretty cool but it doesn't actually work, because user-defined conversion is preferred to ellipsis match, and const reference can bind the temporary result of a user-defined conversion. So char*p; is_related<bool>(p); would return true (tested in VS2010).

    If you want to truly test for an inheritance relationship, a similar approach can be taken but using pointers instead of references.

    0 讨论(0)
  • 2021-02-01 23:18

    By the way, you can use __is_base_of from "type_traits" introduced in std::tr1 (MSCV 2008 compiler has intrinsics support for that).

    0 讨论(0)
  • 2021-02-01 23:23

    Is there any reason you wouldn't use something like this instead:

    template<typename BaseT, typename DerivedT>
    struct IsRelated
    {
        static DerivedT derived();
        static char test(const BaseT&); // sizeof(test()) == sizeof(char)
        static char (&test(...))[2];    // sizeof(test()) == sizeof(char[2])
    
        enum { exists = (sizeof(test(derived())) == sizeof(char)) }; 
    }
    

    ?

    e.g.:

    IsRelated<Base, Derived>::exists
    

    That way you have access to the information at compile-time.

    0 讨论(0)
提交回复
热议问题