[英]Check/modify iterator “constness”
我有两个半密切相关的问题。 给定作为模板参数传递的STL迭代器类型:
enable_if
)此类型对应于非const迭代器? 这个问题来自哪里:
我写了一个小类来促进对向量的算术/关系/代数运算(通过向量我的意思是1d固定大小的数据,而不是STL向量)。 我没有强制使用特定的数据容器,而是定义了一个接口并派生了几个可能的容器,它们基本上“包装”了各种存储数据的方式。 其中一个容器是STL迭代器的包装器,我遇到了一些麻烦。
问题1:
您可以使用以下类型特征:
template<typename T, typename = void>
struct is_const_iterator : std::false_type { };
template<typename T>
struct is_const_iterator<T,
typename std::enable_if<
std::is_const<
typename std::remove_pointer<
typename std::iterator_traits<T>::pointer
>::type
>::value
>::type> : std::true_type { };
这是一个演示:
#include <type_traits>
#include <iterator>
#include <list>
#include <vector>
template<typename T, typename = void>
struct is_const_iterator : std::false_type { };
template<typename T>
struct is_const_iterator<T,
typename std::enable_if<
std::is_const<
typename std::remove_pointer<
typename std::iterator_traits<T>::pointer
>::type
>::value
>::type> : std::true_type { };
int main()
{
typedef std::list<int>::iterator LI;
typedef std::list<int>::const_iterator CLI;
static_assert(is_const_iterator<LI>::value, "!"); // Fires
static_assert(is_const_iterator<CLI>::value, "!"); // Does not fire
typedef std::vector<int>::iterator VI;
typedef std::vector<int>::const_iterator CVI;
static_assert(is_const_iterator<VI>::value, "!"); // Fires
static_assert(is_const_iterator<CVI>::value, "!"); // Does not fire
}
这是一个实例 。
问题2:
使用上述类型特征,这变得简单。 假设您有一个要约束的函数模板foo()
,以便它只接受非const
迭代器:
template<typename It,
typename std::enable_if<!is_const_iterator<It>::value>::type* = nullptr>
void foo(It i)
{
// Does something with i...
}
还有一个简单的演示程序:
int main()
{
std::vector<int> v;
foo(v.begin()); // OK
foo(v.cbegin()); // ERROR!
}
这是一个实例 。
对于1),你可以做这样的事情:
std::is_const<
typename std::remove_reference<
typename std::iterator_traits<Iterator>::reference
>::type
>::value
或这个:
std::is_const<
typename std::remove_reference<
decltype(*iterator)
>::type
>::value
您可以使用这些谓词传递给std::enable_if
来实现2)。
注意:正如R. Martinho Fernandes在评论中所指出的,如果所讨论的迭代器使用与其reference
特征的普通引用不同的类型(例如std::vector<bool>::const_iterator
),则这些谓词将失败。
你可以使用SFINAE
decltype( **(T*)0 = std::move(**(T*)0) )
或(Xeo的偏好)
decltype( *declval<T&>() = std::move(*declval<T&>()) )
检查是否取消引用迭代器会给你一些可分配的东西。 如果集合的元素类型不可分配,那么不完美,但是反正有一个非const_iterator
会有什么好处呢?
不要测试const_iterator
,测试算法实际需要的操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.