有没有办法确保模板参数是一个容器?

时间:2013-07-16 18:14:49

标签: c++ templates

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

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

2 个答案:

答案 0 :(得分:1)

对完整容器的测试很困难且含糊不清。就个人而言,我认为某个容器当且仅当它拥有其直接内容时,但这可能不符合其他人对该术语的使用。

测试迭代性既不困难也不模糊,并且通常是您在函数参数中获取对象时要测试的内容。有可迭代的东西不是容器般的(C ++ 1y或C ++ 1z的string_view,作为一个例子)。

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

for( auto&& a : c ) {}

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

如果上述方法有效,则可以测试在std::beginstd::end在依赖于参数的启用查找上下文中是否返回具有有效std::iterator_traits<>的内容。< / p>

作为一个快速草图,我得到这样的东西:

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 {};

Live example

与此同时,容器很少是统一的。他们最基本的“常见”过程,如添加元素,在签名和语义方面各不相同。 erase(iterator)::allocator_type是容器类结构的两个最常见的功能,但std::array<T,N>T[N]可以说是容器,并且没有属性。

简而言之,除了它们的可迭代性的共同属性之外,容器的差别太大,因为有一个非常有用的is_container<C>特征类。相反,你应该弄清楚你正在寻找的容器的属性(删除元素的能力?能够插入元素?随机访问?)并测试它们。

答案 1 :(得分:1)

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

  

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

适用于C ++ 03及以上版本。