How to test whether class B is derived from template family of classes

后端 未结 3 1754
遇见更好的自我
遇见更好的自我 2020-12-03 19:08

How to test at compile time whether class B is derived from std::vector?

template
struct is_derived_from_vector {
  static const bool value =          


        
相关标签:
3条回答
  • 2020-12-03 19:42

    I was looking for a solution to this problem not long ago and after consulting with

    Modern C++ Design: Generic Programming and Design Patterns Applied

    I was able to build the following which is more or less similar to what was provided in the comments.

    #include <iostream>
    #include <type_traits>
    #include <utility>
    
    template <typename T, template <typename...> class U>
    struct is_derived
    {
    private:
        template <typename...Ts>
        static constexpr std::true_type check(const U<Ts...>&);
        static constexpr std::false_type check(...);
    
    
        template <typename>
        struct is_same
        {
            static constexpr bool value = false;
        };
    
        template <typename...Ts>
        struct is_same <U<Ts...>>
        {
            static constexpr bool value = true;
        };
    
      public:
        static constexpr bool value =
            std::is_same<decltype(check(std::declval<T>())),
                         std::true_type>::value &&
            !is_same<T>::value;
    };
    
    template <typename, typename>
    struct X
    {
    };
    
    template <typename T>
    struct Y : X <T, int>
    {
    };
    
    
    int main(int argc, char **argv) {
    
        std::cout << std::boolalpha << is_derived<Y<int>, X>::value << std::endl;
        std::cout << std::boolalpha << is_derived<X<int,int>, X>::value << std::endl;
        std::cout << std::boolalpha << is_derived<int, X>::value << std::endl;
    
      return 0;
    }
    
    0 讨论(0)
  • 2020-12-03 20:01

    Try this:

    #include <type_traits>
    
    template <typename T, template <typename> class Tmpl>  // #1 see note
    struct is_derived
    {
        typedef char yes[1];
        typedef char no[2];
    
        static no & test(...);
    
        template <typename U>
        static yes & test(Tmpl<U> const &);
    
        static bool const value = sizeof(test(std::declval<T>())) == sizeof(yes);
    };
    

    Usage:

    #include <iostream>
    
    template<class T> struct X {};
    
    struct A : X<int> {};
    
    int main()
    {
        std::cout << is_derived<A, X>::value << std::endl;
        std::cout << is_derived<int, X>::value << std::endl;
    }
    

    Note: In the line marked #1, you could also make your trait accept any template that has at least one, but possibly more type arguments by writint:

    template <typename, typename...> class Tmpl
    
    0 讨论(0)
  • 2020-12-03 20:02

    I had the same situation that I needed to know if a class is derived from a vector(like)-class. Unfortunately there is no C++-11 or variadic macros allowed in my project. So my solution was a mixture of Kerrek's answer and this article with some googletest-code at the end:

    #include <vector>
    
    template <typename T>
    class is_derived_from_vector
    {
        typedef char Yes_t[1];
        typedef char No_t[2];
    
        static No_t& test(const void* const);
    
        template <typename U>
        static Yes_t& test(const std::vector<U>* const);
    
    public:
        static const bool value = ((sizeof(test(static_cast<T*>(0)))) == (sizeof(Yes_t)));
    };
    
    template<class T> struct X {};
    struct A : X<int> {};
    struct B : std::vector<char> {};
    
    TEST(Example, IsDerivedFrom)
    {
       EXPECT_FALSE(is_derived_from_vector<A>::value);
       EXPECT_TRUE(is_derived_from_vector<B>::value);
    }
    

    A common solution for any templates I think would not be possible to define without usage of C++-11 or higher.

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