1

确保模板参数是容器的机制是什么?

或者,如何根据其参数是否为容器来对类/函数进行不同的专业化?

4

2 回答 2

1

另一种方法是使用boost::spirit::traits::is_container<>

mpl::true_如果T定义了以下嵌入类型,则返回: value_typeiteratorsize_typereference。否则它将返回mpl::false_

在 C++03 及更高版本中工作。

于 2013-07-16T21:33:23.567 回答
1

测试一个完整的容器是困难和模棱两可的。就我个人而言,当且仅当它拥有其直接内容时,我才将某物视为容器,但这可能与其他人对该术语的使用不一致。

测试可迭代性既不困难也不模棱两可,并且通常是在函数参数中获取对象时要测试的内容。有些可迭代的东西不是非常像容器(例如 C++1y 或 C++1z string_view)。

在我看来,在 C++11 中,类型 X 的实例 c 是可迭代的 iff:

for( auto&& a : c ) {}

形成良好。为上述选择的措辞意味着您可以使用beginend自由函数重载扩展任何类型以使其可迭代。

如果上述方法可行,一个不错的近似值是测试是否在依赖于参数的启用查找上下文中,std::beginstd::end返回具有有效std::iterator_traits<>.

作为一个速写,我得到这样的东西:

template<typename T, typename=void>
struct is_iterable : std::false_type {};

namespace aux {
  using std::begin;
  // note: no implementation
  template<typename C>
  auto adl_begin( C&& c )->decltype( begin( std::forward<C>(c) ) );
  using std::end;
  // note: no implementation
  template<typename C>
  auto adl_end( C&& c )->decltype( end( std::forward<C>(c) ) );
}
template<typename T>
struct is_iterable<T,
  typename std::enable_if<
    std::is_same<
      typename std::iterator_traits< typename std::decay<decltype( aux::adl_begin( std::declval<T>() ) )>::type >::iterator_category,
      typename std::iterator_traits< typename std::decay<decltype( aux::adl_end( std::declval<T>() ) )>::type >::iterator_category
    >::value
  >::type
> : std::true_type {};

活生生的例子

与此同时,容器很少是统一的。它们最基本的“通用”过程,例如添加元素,在签名和语义上的不同方式彼此不同。 erase(iterator)::allocator_type是类容器结构的两个最常见的特征,但是 astd::array<T,N>T[N]可以说是容器并且没有任何属性。

简而言之,除了它们共同的可迭代性属性之外,容器差异太大,以至于没有一个非常有用的is_container<C>特征类。相反,您应该计算出您正在寻找的容器的哪些属性(删除元素的能力?插入元素的能力?随机访问?)并测试这些属性。

于 2013-07-16T18:35:50.163 回答