detecting typedef at compile time (template metaprogramming)

后端 未结 4 1229
悲&欢浪女
悲&欢浪女 2021-02-03 10:06

I am currently doing some template metaprogramming. In my case I can handle any \"iteratable\" type, i.e. any type for which a typedef foo const_iterator exists in

相关标签:
4条回答
  • 2021-02-03 10:40

    You can create a trait has_const_iterator that provides a boolean value and use that in the specialization.

    Something like this might do it:

    template <typename T>
    struct has_const_iterator {
    private:
        template <typename T1>
        static typename T1::const_iterator test(int);
        template <typename>
        static void test(...);
    public:
        enum { value = !std::is_void<decltype(test<T>(0))>::value };
    };
    

    And then you can specialize like this:

    template <typename T,
              bool IsFundamental = std::is_fundamental<T>::value,
              bool HasConstIterator = has_const_iterator<T>::value>
    struct Foo; // default case is invalid, so no definition!
    
    template <typename T>
    struct Foo< T, true, false>{ 
       void do_stuff(){// bla }
    };
    
    template<typename T>
    struct Foo<T, false, true> {
        void do_stuff(){//bla}
    };
    
    0 讨论(0)
  • 2021-02-03 10:48

    If you simply want if a given type contains const_iterator then following is a simplified version of your code:

    template<typename T>
    struct void_ { typedef void type; };
    
    template<typename T, typename = void>
    struct Foo {};
    
    template<typename T>
    struct Foo <T, typename void_<typename T::const_iterator>::type> {
          void do_stuff(){ ... }
    };
    

    See this answer for some explanation of how this technique works.

    0 讨论(0)
  • 2021-02-03 10:48

    Here's another version of a member type trait check:

    template<typename T>
    struct has_const_iterator
    {
    private:
        typedef char                      yes;
        typedef struct { char array[2]; } no;
    
        template<typename C> static yes test(typename C::const_iterator*);
        template<typename C> static no  test(...);
    public:
        static const bool value = sizeof(test<T>(0)) == sizeof(yes);
    };
    
    0 讨论(0)
  • 2021-02-03 10:55

    There is a couple of ways to do this. In C++03, you could use boost and enable_if to define the trait (docs, source):

    BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator);
    
    template <typename T, typename Enable = void>
    struct Foo;
    
    template <typename T>
    struct Foo< T, typename boost::enable_if<boost::is_fundamental<T> >::type>{ 
       void do_stuff(){ ... }
    };
    
    template<typename T>
    struct Foo<T, typename boost::enable_if<has_const_iterator<T> >::type> {
        void do_stuff(){ ... }
    };
    

    In C++11, you could use Tick like this:

    TICK_TRAIT(has_const_iterator)
    {
        template<class T>
        auto require(const T&) -> valid<
            has_type<typename T::const_iterator>
        >;
    };
    
    template <typename T, typename Enable = void>
    struct Foo;
    
    template <typename T>
    struct Foo< T, TICK_CLASS_REQUIRES(std::is_fundamental<T>::value)>{ 
       void do_stuff(){ ... }
    };
    
    template<typename T>
    struct Foo<T, TICK_CLASS_REQUIRES(has_const_iterator<T>())> {
        void do_stuff(){ ... }
    };
    

    Also with Tick you can further enhance the trait to actually detect that the const_iterator is actually an iterator, as well. So say we define a simple is_iterator trait like this:

    TICK_TRAIT(is_iterator,
        std::is_copy_constructible<_>)
    {
        template<class I>
        auto require(I&& i) -> valid<
            decltype(*i),
            decltype(++i)
        >;
    };
    

    We can then define has_const_iterator trait to check that the const_iterator type matches the is_iterator trait like this:

    TICK_TRAIT(has_const_iterator)
    {
        template<class T>
        auto require(const T&) -> valid<
            has_type<typename T::const_iterator, is_iterator<_>>
        >;
    };
    
    0 讨论(0)
提交回复
热议问题