“Inverse SFINAE” to avoid ambiguous overload

前端 未结 2 867
野性不改
野性不改 2020-12-21 17:36

How can I prevent the first template below from instantiating if the second template instantiates? (i.e. if both static_cast(0) and T::zero()

2条回答
  •  情深已故
    2020-12-21 18:01

    Without enable_if, relying on built-in rules of integer conversion ranks (conversion of 0 -> int is better than 0 -> char, which makes the former a first choice candidate, and the latter a viable second choice candidate):

    template 
    auto zero_helper(char) -> decltype(static_cast(0))
    {
        return static_cast(0);
    }
    
    template 
    auto zero_helper(int) -> decltype(T::zero())
    {
        return T::zero();
    }
    
    template 
    auto zero() -> decltype(auto)
    {
        return zero_helper(0);
    }
    

    DEMO

    With your own enable_if predicate (similar to the std::void_t technique):

    #include 
    
    template 
    struct voider { using type = void; };
    
    template 
    using void_t = typename voider::type;
    
    template >
    struct has_zero : std::false_type {};
    
    template 
    struct has_zero> : std::true_type {};
    
    template 
    auto zero()
        -> typename std::enable_if::value, decltype(T::zero())>::type
    {
        return T::zero();
    }
    
    template 
    auto zero()
        -> typename std::enable_if::value, T>::type
    {
        return static_cast(0);
    }
    

    DEMO 2

提交回复
热议问题