setAllValues
вызывается с Lvalue:
template< class D > bool Region< D >::setRegion( D& dataPack ) {
auto func = std::bind( &Region::computeValue, this,
std::placeholders::_1, std::placeholders::_2 );
return setAllValues( dataPack, func ); // func as named object is Lvalue
}
Из-за правил перенаправления ссылки Fn
выводится как Fn&
- как ссылка Lvalue.
template< class D >
template< class Fn > bool Region< D >::setAllValues( D& dataPack,
Fn&& fn ) // Fn is Fn&
In ниже
&Region::setRegionValue< std::remove_reference_t< Fn > >,
^^^ you put explicitly type in template argument list
ссылка на Fn
удалена. Поскольку вы явно указываете параметр setRegionValue
как Fn
, тип его третьего параметра - Fn&&
- Rvalue ref. Пересылка Lvalue по forward<Fn>(fn)
в Rvalue не совпадает, и поэтому код не удался.
Чтобы обработать Fn
как Lvalue, вы можете написать:
template< class D >
template< class Fn > bool Region< D >::setAllValues( D& dataPack,
Fn&& fn ) { // Fn& &&fn
for ( int indx = 0; indx < 10; ++indx )
{
int input = indx * 5;
m_futures.push_back( std::async( std::launch::async,
&Region::setRegionValue< Fn >, // <- here is Fn&
this, input, std::ref( dataPack ),
std::ref( fn ) ) ); // <-
}
return true;
}
в случае &Region::setRegionValue< Fn >
, setRegionValue
принимает третий параметр как Fn&
. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * T ПАНКОНОМИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ * Для использования Lvalue в std::reference_wrapper
.
Рабочая версия 1
.
Приведенный выше код не обрабатывает регистр при передаче Rvalue в setAllValues
.
Если вы написали:
return setAllValues( dataPack, std::bind( &Region::computeValue, this,
std::placeholders::_1, std::placeholders::_2 ) );
определение setAllValues
должно быть:
template< class D >
template< class Fn > bool Region< D >::setAllValues( D& dataPack,
Fn&& fn ) {
for ( int indx = 0; indx < 10; ++indx )
{
int input = indx * 5;
m_futures.push_back( std::async( std::launch::async,
&Region::setRegionValue< Fn >,
this, input, std::ref( dataPack ),
std::forward<Fn>( fn ) ) );
}
return true;
}
, в котором fn
как временное только что переадресовано.
Рабочая версия 2
Трудно разместить std::ref
(что требуется std::async
) с std::forward
в одном вызове, вы можете сделать две перегрузки:
template < class Fn > bool setAllValues( D&, Fn&& ); // uses std::forward
template < class Fn > bool setAllValues( D&, Fn& ); // uses std::ref
для обработки обоих случаев.