确保模板参数是容器的机制是什么?
或者,我如何根据其参数是否为容器对类/函数进行不同的特化?
答案 0 :(得分:1)
对完整容器的测试很困难且含糊不清。就个人而言,我认为某个容器当且仅当它拥有其直接内容时,但这可能不符合其他人对该术语的使用。
测试迭代性既不困难也不模糊,并且通常是您在函数参数中获取对象时要测试的内容。有可迭代的东西不是容器般的(C ++ 1y或C ++ 1z的string_view
,作为一个例子)。
在我看来,在C ++ 11中,类型X的实例c是可迭代的iff:
for( auto&& a : c ) {}
状态良好。为上述选择的措辞意味着您可以使用begin
和end
自由函数重载来扩展任何类型,以使其可迭代。
如果上述方法有效,则可以测试在std::begin
和std::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 {};
与此同时,容器很少是统一的。他们最基本的“常见”过程,如添加元素,在签名和语义方面各不相同。 erase(iterator)
和::allocator_type
是容器类结构的两个最常见的功能,但std::array<T,N>
和T[N]
可以说是容器,并且没有属性。
简而言之,除了它们的可迭代性的共同属性之外,容器的差别太大,因为有一个非常有用的is_container<C>
特征类。相反,你应该弄清楚你正在寻找的容器的属性(删除元素的能力?能够插入元素?随机访问?)并测试它们。
答案 1 :(得分:1)
另一种方法是使用boost::spirit::traits::is_container<>
如果
mpl::true_
定义了以下嵌入类型,则返回T
:value_type
,iterator
,size_type
和reference
。否则它将返回mpl::false_
。
适用于C ++ 03及以上版本。