Which of the partial specialization options is better than C++



  • I know there are a few options, but I don't know what and when to use.

    Let's say I wrote a sign-up class that magically follows you as Big Brother, so that you don't get a zero-indicator, clears your memory after you're out of sight, etc.

    template <class Ty>
    class super_puper_smart_pointer{
      publuc:
        super_puper_smart_pointer(Ty* ptr) 
          : _ptr(ptr) {
        }
    

    // ...

    private:
    Ty* _ptr;
    };

    And then, suddenly, there's an awareness that iterators would actually be good to check. Like this code.

    std::vector<int> m_numbers = {1, 2, 3};

    auto first = std::find(v.begin(), v.end(), 0);

    // assert(find != v.end);

    if(*first == 0) {
    // ...
    }

    There was a little mistake. We forgot to check that the value found is not the end of sequence.

    In order to make life easier, let's write a class box for the heterans, which in the designer will make some checks.

    So, after taking stock, we need a sign-up class and a guide class.

    To be able to distinguish one from another, we need:

    • std:is_pointer broadcast. ♪ ♪ ation
    • is_iteratorrail. ♪ ♪ ationimplementation below
        template <class It>
    using iterator_category_t = typename ::std::iterator_traits<It>::iterator_category;

    template &lt;class Ty, class = void&gt;
    inline constexpr bool is_iterator_v = false;
    
    template &lt;class Ty&gt;
    inline constexpr bool is_iterator_v&lt;Ty, ::std::void_t&lt;iterator_category_t&lt;Ty&gt;&gt;&gt; = true;
    

    The last step left was to implement the classroom with partial specialization.

    Option 1

    // Реализация для указателя
    template <class Ty, std::enable_if_t<std::is_pointer_v<Ty>> = nullptr>
    class super_puper_smart_pointer{
    publuc:
    super_puper_smart_pointer(Ty ptr)
    : _ptr(ptr) {
    // какие-то проверки для указателя
    }

    template &lt;class U&gt;
    friend class super_puper_smart_pointer;
    

    private:
    Ty _ptr;
    };

    // Реализация для итератора
    template <class Ty, std::enable_if_t<is_iterator_v<Ty>> = nullptr>
    class super_puper_smart_pointer{
    publuc:
    super_puper_smart_pointer(Ty it)
    : _it(it) {
    // какие-то проверки для итератора
    }

    template &lt;class U&gt;
    friend class super_puper_smart_pointer;
    

    private:
    Ty _it;
    };

    Option 2

    // Частичное объявление
    template <class Ty, class = void>
    class super_puper_smart_pointer;

    // Реализация для указателя
    template <class Ty>
    class super_puper_smart_pointer<std::enable_if_t<std::is_pointer_v<Ty>, int>>{
    publuc:
    super_puper_smart_pointer(Ty ptr)
    : _ptr(ptr) {
    // какие-то проверки для указателя
    }

    template &lt;class U&gt;
    friend class super_puper_smart_pointer;
    

    private:
    Ty _ptr;
    };

    // Реализация для итератора
    template <class Ty>
    class super_puper_smart_pointer<Ty, std::enable_if_t<is_iterator_v<Ty>, int>>{
    publuc:
    super_puper_smart_pointer(Ty it)
    : _it(it) {
    // какие-то проверки для итератора
    }

    template &lt;class U&gt;
    friend class super_puper_smart_pointer;
    

    private:
    Ty _it;
    };

    Issues:

    1. Why do you have to write somewhere? std::enable_if_t<is_iterator_v<Ty>> = nullptr♪ and somewhere ♪ std::enable_if_t<std::is_pointer_v<Ty>, int>
    2. How should I write?
    3. Learn how to write rightly because I've even made mistakes on the question, I don't understand this syntax.
    4. You can do the same through a void_t, I think?
    5. When to write = nullptr
    6. When to write enable_ifand when enable_if_t



  • It's better not to specialize in different things. Okay, vector<bool> Frequently exemplify as errors, despite the fact that the dynamic batset is in principle a suitable container.

    Testing the iterator and checking the indicator -- different checks, so specializations will be too different!

    It's better to check the heterans from outside, but to do it on the side. They have more access to the details of implementation.

    The realisation of STL is usually already in the debag mode. The best way to make such checks if they are not suitable is to make their STL containers.


    std::enable_if_t<is_iterator_v<Ty>>* = nullptr and std::enable_if_t<std::is_pointer_v<Ty>, int> = 0 - Same, delicious. It's a way to kill specialization through SFINAE if the condition is false.

    void_t It's another way to kill specialization through SFINAE if the sub-standard fails. For example, the method is tested.

    enable_ifand other _t versions of types of functions -- more inconvenienced options that were needed before using in the context of template typedef.


Log in to reply
 

Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2