本文介绍了如何SFINAE输出非容器参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板函数,我只想为标准容器(或容器兼容标准容器,至少提供一个 begin()成员函数)启用。我用以下方式SFINAE非容器:

I have a template function that I want to enable only for standard containers (or containers compatible with standard containers, which at least provide a begin() member function). I'm SFINAE-ing out non-containers in the following way:

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_same code> decltype 看起来不太优雅。有没有更好的方法这样做?

The std::is_same and decltype don't look too elegant. Is there any better way of doing this?

PS:我需要SFINAE在这里,因为我有一个不同的重载

PS: I need the SFINAE here because I have a different overload

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

f(some_Eigen_matrix)容器重载最终被选中,然后编译器会发出一个错误,缺少 begin()

and whenever I try f(some_Eigen_matrix), the Container overload ends up being picked up, then the compiler spits out an error because the type is lacking begin().

推荐答案

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3911rel =nofollow> void_t ,我们可以创建一个类型特征为 begin() end()检查,如 typename T :: iterator ,您只能保持打桩表达式):

Using void_t, we can just make a type trait for having begin() and end() (and anything else you might want to check for, like typename T::iterator, you can just keep piling expressions on):

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:

And then just SFINAE on that:

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

此外,如果你真的想验证 begin()返回 T :: iterator (或者至少它们是等同的),你也可以这样做:

Also, if you really wanted to verify that begin() gives you back a T::iterator (or at least that they're equality comparable), you can do that too:

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

这篇关于如何SFINAE输出非容器参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 09:01