我有一个模板类,其容器类型定义为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&non-const .
我试图通过获取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返回非const值类型,而不管std :: set :: begin()中的实数迭代器是否取消引用const T& .
我的目标是推断出作为参数提供的函数的正确签名 . 如果我将所提到的函数定义为(const std :: function&aFnc),那么将为std :: set编译所有内容,但不适用于其他容器类型,如vector .
2 回答
你这里不需要
std::function
. 让aFnc
成为推导出的模板参数 .要么
std::set
不允许通过迭代器修改元素 .std::set::iterator
和std::set::const_iterator
都是常量迭代器(甚至可以是相同的类型) . 这是因为std::set
必须不允许重复 .所以无论什么类型的演绎巫术都不可能在这种迭代中修改
set
的元素 . 如果aFnc
需要修改元素,则无法使用std::set
.如果相反
aFnc
不修改其参数,那么你需要使arg const: