How to use sfinae for selecting constructors?

后端 未结 5 1843
北海茫月
北海茫月 2020-11-29 04:24

In template meta programming, one can use SFINAE on the return type to choose a certain template member function, i.e.

template struct          


        
5条回答
  •  离开以前
    2020-11-29 05:10

    There are many ways to trigger SFINAE, being enable_if just one of them. First of all:

    Wats is std::enable_if ?

    It's just this:

    template enable_if{ typedef T type; };
    template enable_if {};
    template using enable_if_t = typename enable_f::type;
    

    The idea is to make typename enable_if::type to be an error, hence make any template declaration containing it skipped.

    So how can this trigger function selection?

    Disabling functions

    The idea is making the declaration erroneous in some part:

    By return type

    template
    std::enable_if_t::value,Return_type> function(Type);
    

    By a actual parameter

    template
    return_type function(Type param, std::enable_if_t::value,int> =0) 
    

    By a template parameter

    template::value,int> =0> //note the space between > and =
    return_type function(Type param) 
    

    Selecting functions

    You can parametrise different alternatives with tricks like this:

    tempplate struct ord: ord{};
    struct ord<0> {};
    
    template =0>
    retval func(ord<3>, T param) { ... }
    
    template =0>
    retval func(ord<2>, T param) { ... }
    
    template =0>
    retval func(ord<1>, T param) { ... }
    
    template // default one
    retval func(ord<0>, T param) { ... }
    
    // THIS WILL BE THE FUCNTION YOU'LL CALL
    template
    retval func(T param) { return func(ord<9>{},param); } //any "more than 3 value"
    

    This will call the first/second/third/fourth function if condition3 is satisfied, than condition2 than condition1 than none of them.

    Other SFINAE triggers

    Writing compile-time conditions can be either a matter of explicit specialization or a matter of unevaluated expression success/failure:

    for example:

    template
    struct is_vector: std::false_type {};
    template
    struct is_vector >:: std::true_type {};
    

    so that is_vector::value is false but is_vecttor >::value is true

    Or, by means of introspection, like

    template
    struct is_container: std::false_type {};
    
    template
    struct is_container()),
      std::end(std::declval()),
      std::size(std::declval()),
      void(0))>: std::true_type {};
    

    so that is_container::value will be true if given X x, you can compile std::begin(x) etc.

    The trick is that the decltype(...) is actually void (the , operator discards the previous expressions) only if all the sub-expressions are compilable.


    There can be even many other alternatives. Hope between all this you can find something useful.

提交回复
热议问题