не удалось вывести / заменить аргумент шаблона в многопоточности - PullRequest
0 голосов
/ 07 февраля 2020

Я сталкиваюсь с этой проблемой вывода / замены шаблона при прохождении функции. Может кто-нибудь помочь, я был бы очень признателен:

#include <iostream>
#include <vector>
#include <future>


template< class D > class Region
{

public:

  virtual bool                   setRegion( D& );

protected:


  int                            computeValue( int input, D& dataPack );
  template < class Fn > bool     setRegionValue( const int, D&, Fn&& );
  template < class Fn > bool     setAllValues( D&, Fn&& );

protected:

  std::vector< int >                  m_regionValues;
  std::vector< std::future< bool > >  m_futures;
};



template< class D > int Region< D >::computeValue( const int input,
                                                   D& dataPack )
{
  return input * dataPack.getData();
}


template< class D > 
template < class Fn > bool Region< D >::setRegionValue( const int input,
                                                        D& dataPack,
                                                        Fn&& function )
{
  int output = function( input, dataPack, output );
  m_regionValues.push_back( output * 2 );
  //check..
  return true;
}
  

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< std::remove_reference_t< Fn > >,
                                     this, input, std::ref( dataPack ),
                                     std::forward< Fn >( fn ) ) );
  }

  //check thread status..
  return true;
}


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 );
}


struct Region1Data
{
  int        m_regionData;
  int        getData() const;
};


int Region1Data::getData() const
{
  return m_regionData;
}
  

class Region1: public Region< Region1Data >
{
public:

  bool                         setRegion( Region1Data& );
  void                         outputValue();
};


void Region1::outputValue()
{
  //..
}


bool Region1::setRegion( Region1Data& dataPack )
{
  if ( !Region::setRegion( dataPack ) )
  {
    return false;
  }

  outputValue();
  return true;
}


int main()
{
  Region1 thisRegion;
  Region1Data dataPack;
  dataPack.m_regionData = 10;
  
  thisRegion.setRegion( dataPack );
  return 0;
}

Вот ошибки при компиляции кода:

пример. cpp: В экземпляре 'bool Region :: setAllValues ​​(D &, Fn &&) [с Fn = std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder <2>)> &; D = Region1Data] ': пример. cpp: 72: 39: требуется из примера' bool Region :: setRegion (D &) [with D = Region1Data] '. cpp: 106: 17: требуется отсюда пример. cpp: 59: 63: ошибка: нет соответствующей функции для вызова 'asyn c (std :: launch,, Region , int &, std :: reference_wrapper, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder <2>)> &) 'std :: forward (fn))); ^ пример. cpp: 59: 63: примечание: кандидаты: В файле, включенном из примера. cpp: 3: 0: /opt/devl/optimize/gcc-4.9.3/include/c++/ 4.9.3 / future: 75: 5: note: шаблон std :: future :: type> std :: asyn c (std :: launch, _Fn &&, _Args && ...) asyn c (запуск __policy, _Fn && __fn, _Args && ... __args) ^ /opt/devl/optimize/gcc-4.9.3/include/c++/4.9.3/future:75:5: note: сбой вывода / замены аргументов шаблона: / opt /devl/optimize/gcc-4.9.3/include/c++/4.9.3/future: в замене 'шаблона std :: future :: type> std :: asyn c (std :: launch, _Fn &&, _Args && ...) [с _Fn = bool (Region :: ) (int, Region1Data &, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder < 1>, std :: _ Placeholder <2>)> &&); _Args = {Region , int &, std :: reference_wrapper, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder <2> )> &}] ': пример. cpp: 59: 63: требуется от' bool Region :: setAllValues ​​(D &, Fn &&) [with Fn = std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder <2>)> &; D = Region1Data] 'пример. cpp: 72: 39: требуется из примера' bool Region :: setRegion (D &) [with D = Region1Data] '. cpp: 106: 17: требуется отсюда / opt / devl /optimize/gcc-4.9.3/include/c++/4.9.3/future:75:5: ошибка: нет типа с именем 'type' в 'классе std :: result_of :: (Region * 1016) *, int &, std :: reference_wrapper, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder <2>)> &)) ( int, Region1Data &, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder <2>)> &&)> 'пример. cpp : В экземпляре 'bool Region :: setAllValues ​​(D &, Fn &&) [с Fn = std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _Placeholder <2>)> &; D = Region1Data] ': пример. cpp: 72: 39: требуется из примера' bool Region :: setRegion (D &) [with D = Region1Data] '. cpp: 106: 17: требуется отсюда / opt / devl / optimize / g cc -4.9.3 / include / c ++ / 4.9.3 / future: 95: 5: примечание: шаблон std :: future :: type> std :: asyn c (_ Fn &&, _Args &&. ..) asyn c (_ Fn && __fn, _Args && ... __args) ^ /opt/devl/optimize/gcc-4.9.3/include/c++/4.9.3/future:95:5: note: Ошибка вывода / замены аргумента шаблона: /opt/devl/optimize/gcc-4.9.3/include/c++/4.9.3/future: при замене шаблона шаблон std :: future :: type> std :: asyn c (_ Fn &&, _Args && ...) [with _Fn = std :: launch; _Args = {bool (Region :: ) (int, Region1Data &, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder < 2>)> &&), Region , int &, std :: reference_wrapper, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _Placeholder <2>)> &}] ': пример. cpp: 59: 63: требуется от' bool Region :: setAllValues ​​(D &, Fn &&) [with Fn = std :: _ Bind :: *) (int, Region1Data & )> (Регион , std :: _ Placeholder <1>, std :: _ Placeholder <2>)> &; D = Region1Data] 'пример. cpp: 72: 39: требуется от' bool Region :: setRegion (D &) [with D = Region1Data] ' пример. cpp: 106: 17: необходимо отсюда /opt/devl/optimize/gcc-4.9.3/include/c++/4.9.3/future:95:5: ошибка: тип не указан 'тип 'in' класс std :: result_of :: ) (int, Region1Data &, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _Placeholder <2>)> &&), Region , int &, std :: reference_wrapper, std :: _ Bind :: *) (int, Region1Data &)> (Region , std :: _ Placeholder <1>, std :: _ Placeholder <2>)> &)> '

1 Ответ

0 голосов
/ 07 февраля 2020

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

для обработки обоих случаев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...