C++ 如何正确推断从std::set::begin()返回的迭代器的解引用类型?
我有一个模板类,其容器类型定义为StorageType模板C++ 如何正确推断从std::set::begin()返回的迭代器的解引用类型?,c++,C++,我有一个模板类,其容器类型定义为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 );
StorageType mStorage;
....
void iterate( const std::function<bool( typename StorageType::value_type& )>& aFnc )
{
for( auto it = mStorage.begin(); it != mStorage.end(); ++it )
{
aFnc( *it );
}
}
StorageType-mStorage;
....
void iterate(const std::function和aFnc)
{
for(auto it=mStorage.begin();it!=mStorage.end();++it)
{
aFnc(*it);
}
}
这适用于大多数stl容器。但说到std::set,我面临一个问题,因为mStorage.begin()返回常量迭代器,而aFnc(*it)编译失败,因为aFnc函数需要StorageType::value\u 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 )
void迭代(std::function&aFnc)
但似乎std::iterator\u traits::value\u type返回非常量值类型,而不管std::set::begin()中的实际迭代器是否取消对常量T的引用
我的目标是推导作为参数提供的函数的正确签名。如果我将所提到的函数定义为(const std::function&aFnc),那么所有内容都将为std::set编译,但不适用于其他容器类型,如vector。
std::set
不允许通过迭代器修改元素。std::set::iterator
和std::set::const_iterator
都是常量迭代器(甚至可能是相同的类型)。这是因为std::set
必须是不允许重复的
所以,无论是哪种类型的演绎,都不可能在这种迭代中修改集合
的元素。如果aFnc
需要修改元素,则不能使用std::set
如果aFnc不修改其参数,则需要使arg常量:
using StoredType = typename StorageType::value_type;
void iterate(const std::function<bool(const StoredType&)>& aFnc)
使用StoredType=typename StorageType::value\u type;
void iterate(const std::function和aFnc)
这里不需要std::function
。只需将aFnc
作为推导的模板参数
template <typename Func>
void iterate( Func aFnc )
{
for( auto & obj : mStorage )
{
aFnc( obj );
}
}
模板
无效迭代(Func aFnc)
{
用于(自动和车载:mStorage)
{
aFnc(obj);
}
}
或
模板
无效迭代(Func&&aFnc)
{
std::for_each(mStorage.begin()、mStorage.end()、std::forward(aFnc));
}
存储类型的定义是什么?std::set
不允许修改其元素。从C++17开始,您可以使用extract
member函数,但这是一种不同的方法,与您发布的方法不匹配。在任何情况下,您希望何时交替注入std::vector
或std::set
?我看不出一个合理的用例,它们是完全不同的容器。@MatthieuBrucher这是一个模板参数。事实上,应该是常量&,而不仅仅是&…@lubgr。我知道它不允许修改。我的目标是推导作为参数提供的函数的正确签名。如果我将set定义为(const std::function&aFnc),那么所有的东西都将为set编译,但对于其他容器类型(如vector)则不起作用。这确实是一个解决方案。我已经在很多地方使用了这个函数,如果我要引入一个模板参数,我将不得不更改上百个地方。@t不,您不需要更改调用位置。可以推导函数模板参数。我是否应该将函数调用从iterate(aFnc)更改为iterate(aFnc)以进行编译?我想是的。不,你不需要iterate(aFnc)
在该上下文中的意思与iterate(aFnc)
相同。您完全正确。这是我可以接受的解决方案。出于某种原因,我将不得不指定一个模板括号。
template <typename Func>
void iterate( Func && aFnc )
{
std::for_each( mStorage.begin(), mStorage.end(), std::forward<Func>(aFnc) );
}