Template class methods definition with enable_if as template parameter

前端 未结 2 1440
天涯浪人
天涯浪人 2021-02-05 22:07

I asked this question earlier where a solution was presented. The solution is great as far as the question is concerned, but now I am confused on how I would define the methods

相关标签:
2条回答
  • 2021-02-05 22:21

    Here's how SFINAE can actually work with partial specialization:

    template<typename T, typename Sfinae = void>
    struct Foo {
        /* catch-all primary template */
        /* or e.g. leave undefined if you don't need it */
    };
    
    template<typename T>
    struct Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type> {
        /* matches types derived from BasePolicy */
        Foo();
    };
    

    The definition for that constructor can then be awkwardly introduced with:

    template<typename T>
    Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type>::Foo()
    {
        /* Phew, we're there */
    }
    

    If your compiler supports template aliases (it's a C++11 feature) that then you can cut a lot of the verbosity:

    template<typename T>
    using EnableIfPolicy = typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type;
    
    // Somewhat nicer:
    
    template<typename T>
    struct Foo<T, EnableIfPolicy<T>> {
        Foo();
    };
    
    template<typename T>
    Foo<T, EnableIfPolicy<T>>::Foo() {}
    

    Note: your original answer referred to utilies from Boost, like boost::enable_if_c and boost::is_base_of. If you're using that instead of std::enable_if and std::is_base_of (which are from C++11), then usage looks like

    typename boost::enable_if<boost::is_case_of<BasePolicy, T> >::type
    

    which has the advantage of getting rid of one ::value.

    0 讨论(0)
  • 2021-02-05 22:32

    From the looks of it, you want to do something along the lines of this:

    template <typename Policy,
              typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type >
    struct Foo;
    
    template <typename Policy>
    struct Foo<Policy> {
        Foo();
    };
    
    template <typename Policy>
    Foo<Policy>::Foo() {
    }
    

    This sneakily takes advantage of the default argument in a few places: don't get confused, there is an implicit void sitting in several locations.

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