问题描述
我有一个模板函数,我只想为标准容器(或容器兼容标准容器,至少提供一个 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输出非容器参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!