代码之家  ›  专栏  ›  技术社区  ›  Jonathan Mee

使能器中的短路操作器

  •  4
  • Jonathan Mee  · 技术社区  · 7 年前

    array<int, 3> 或者 int[3] enable_if :

    template<typename T>
    enable_if_t<is_array_v<T> && extent_v<T> == 3U || !is_array_v<T> && tuple_size<T>::value == 3U> foo(const T& param) {}
    

    不幸的是 内景[3] tupple_size

    我也尝试过使用 conditional 但同样的问题是,要确保这两个选项对 T

    我知道我可以通过专攻来做到这一点。但是代码在函数体中是完全相同的。我讨厌这样一个事实:当实现是相同的时候,我是专门化的。

    3 回复  |  直到 7 年前
        1
  •  7
  •   T.C. Yksisarvinen    7 年前

    利用这样一个事实 extent<T> disjunction 源于短路列表中的第一个truthy类型:

    template<typename T>
    enable_if_t<disjunction<extent<T>, tuple_size<T>>::value == 3U> foo(const T& param) {}
    

    这可能太聪明了。请注意,您不能使用 disjunction_v 在这里。


    conditional 应该也不错。诀窍是不要要求 ::value

    template<typename T>
    enable_if_t<conditional_t<is_array_v<T>, extent<T>, tuple_size<T>>::value == 3U> 
        foo(const T& param) {}
    
        2
  •  4
  •   Karl    7 年前

    简言之,模板替换必须始终有效。只需定义一个特定的模板来匹配数组可能会更简单:

    template <typename T>
    struct IsArrayInt3 { enum: bool { value = false }; };
    
    template <>
    struct IsArrayInt3<int[3]> { enum: bool { value = true }; };
    
    template <>
    struct IsArrayInt3<std::array<int, 3>> { enum: bool { value = true }; };
    
        3
  •  3
  •   marc_s MisterSmith    7 年前

    namespace detail
    {
    template <class T>
    auto foo_impl(const T& a)
    {
        // common code
    }
    }
    
    template <class T>
    auto foo(const std::array<T, 3>& a)
    {
        detail::foo_impl(a);
    }
    
    template <class T>
    auto foo(const T(&a)[3])
    {
        detail::foo_impl(a);
    }
    

    这是明确的,无需麻烦,并避免代码重复。

    template <class T, std::size_t Size>
    struct my_is_array : std::false_type
    {};
    
    template <class T, std::size_t Size>
    struct my_is_array<std::array<T, Size>, Size> : std::true_type
    {};
    
    template <class T, std::size_t Size>
    struct my_is_array<T[Size], Size> : std::true_type
    {};
    
    template<typename T>
    std::enable_if_t<my_is_array<T, 3>::value> foo(const T& param) {}
    

    或者(实际上我更喜欢这个):

    template <class T>
    struct array_size_or_zero : std::integral_constant<std::size_t, 0>
    {};
    
    template <class T, std::size_t Size>
    struct array_size_or_zero<std::array<T, Size>> : std::integral_constant<std::size_t, Size>
    {};
    
    template <class T, std::size_t Size>
    struct array_size_or_zero<T[Size]> : std::integral_constant<std::size_t, Size>
    {};
    
    template<typename T>
    std::enable_if_t<array_size_or_zero<T>::value == 3> foo(const T& param) {}
    

    小心!!: foo