我有一个模板类,其容器类型定义为 StorageType 模板。
StorageType mStorage;
....
void iterate( const std::function<bool( typename StorageType::value_type& )>& aFnc )
{
for( auto it = mStorage.begin(); it != mStorage.end(); ++it )
{
aFnc( *it );
}
}
这适用于大多数 STL 容器。但是当谈到 std::set 时,我面临一个问题,因为 mStorage.begin() 返回 const_iterator ,而 aFnc( *it ) 编译失败,因为 aFnc 函数需要 StorageType::value_type& 这是非常量的。
我尝试通过获取 std::set::begin 的结果并推导所接收的迭代器的取消引用类型来推导正确的类型,如下所示:
void iterate( std::function<void(typename std::iterator_traits<std::result_of<decltype(&std::set<ValueType>::begin)(std::set<ValueType>)>::type>::value_type& )>& aFnc )
但似乎 std::iterator_traits<>::value_type 返回非常量值类型,无论 std::set::begin() 中的实际迭代器取消引用 const T&。
我的目标是推断出作为参数提供的函数的正确签名。如果我将提到的函数定义为( const std::function& aFnc ),则所有内容都将为 std::set 进行编译,但不适用于其他容器类型(如 vector )。
最佳答案
std::set
不允许通过迭代器修改元素。 std::set::iterator
和 std::set::const_iterator
都是常量迭代器(甚至可能是相同的类型)。这是因为 std::set
必须不允许重复。
因此,无论使用何种类型推导魔法,都不可能在这种 for 迭代中修改 set
的元素。如果 aFnc
需要修改元素,则不能使用 std::set
。
如果 aFnc
不修改其参数,那么您需要将参数设为常量:
using StoredType = typename StorageType::value_type;
void iterate(const std::function<bool(const StoredType&)>& aFnc)
关于c++ - 如何正确推导从 std::set::begin() 返回的迭代器的取消引用类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53594471/