如何删除非containers参数

How to SFINAE out non-containers parameters

本文关键字:containers 参数 删除 何删除      更新时间:2023-10-16

i具有一个模板功能,我只想适用于标准容器(或与标准容器兼容的容器,至少提供begin()成员功能)。我正在以以下方式进行非族裔:

template<typename Container>
typename Container::value_type 
f(const Container& c,
    typename std::enable_if<
        std::is_same<
            decltype(*c.begin()),
            typename Container::value_type
        >::value
    >::type* = nullptr)
{
    // implementation here
}

std::is_samedecltype看起来不太优雅。有什么更好的方法吗?

ps:我在这里需要sfinae,因为我有不同的超载

template<typename Derived>
f(const Eigen::MatrixBase<Derived>& A)

,每当我尝试f(some_Eigen_matrix)时,Container过载最终被捡起,然后编译器会出现错误,因为类型缺少begin()

使用 void_t,我们只能制作一个类型特征,以使其具有begin()end()(以及您可能需要检查的其他任何内容,例如typename T::iterator,您可以保持堆积的表达方式):

template <typename T, typename = void>
struct is_std_container : std::false_type { };
template <typename T>
struct is_std_container<T,
    void_t<decltype(std::declval<T&>().begin()),
           decltype(std::declval<T&>().end()),
           typename T::value_type
           >>
    : std::true_type { };

然后就sfinae:

template <typename Container>
typename std::enable_if<
    is_std_container<Container>::value,
    typename Container::value_type
>::type 
f(const Container& c) { .. }

另外,如果您真的想验证begin()是否会给您T::iterator(或者至少是它们平等可比性),则也可以做到这一点:

void_t<
    decltype(begin(std::declval<T&>()) == std::declval<typename T::iterator>())
>