当前位置: 首页 > 知识库问答 >
问题:

模板参数演绎/替换在多线程处理中失败

苏乐
2023-03-14

在传递函数时,我遇到了这个模板演绎/替换问题。有人可以帮忙吗,我非常感谢:

#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) 的实例化中

共有1个答案

韩玉石
2023-03-14

setAllValues使用左值调用:

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
}

由于转发引用规则,< code>Fn被推导为< code>Fn

template< class D > 
template< class Fn > bool Region< D >::setAllValues( D& dataPack,
                                                     Fn&& fn )          // Fn is Fn& 

在下面

&Region::setRegionValue< std::remove_reference_t< Fn > >,
                        ^^^ you put explicitly type in template argument list 

删除Fn的引用性。因为您将setRealonValue的显式参数指定为Fn,所以它的第三个参数的类型是Fn

要将 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;
}

在以下情况下

工作版本 1

上述代码不处理将右值传递到<code>setAllValues</code>中的情况。

如果你写道:

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

很难在一次调用中容纳< code>std::ref(这是< code>std::async所必需的)和< code>std::forward,您可以进行两次重载:

template < class Fn > bool     setAllValues( D&, Fn&& );   // uses std::forward
template < class Fn > bool     setAllValues( D&, Fn& );    // uses std::ref

处理这两种情况。

 类似资料:
  • 这些代码如下: 使用G++4.8.2错误信息编译:

  • 假设有一个模板函数 接受任意数量的参数。给定最后一个参数始终是 ,我如何实现下面显示的 模板,以便 包含此 的参数? 例如,如果像这样调用,应该是: 我的第一个想法是: 但这不会编译: 问题一: 为什么这不能编译?为什么模板参数演绎失败? 最终,我想出了这个解决方案: 这里,是,即中的最后一种类型。然后,的临时值被传递到,其中。这行得通,但在我看来很难看。 问题二: 我想知道如果没有两个函数和的临

  • 考虑以下代码: 失败的行在G7下返回以下错误: 这是正常的还是编译器错误?

  • C 17标准(最终草案)的[temp.arg.explicit]/3说明了使用显式指定的模板参数列表推导函数模板参数: 在扣除完成且失败的情况下,或[...],如果指定了模板参数列表,并且它与任何默认模板参数一起标识了单个函数模板专门化,则template-id是函数模板专门化的左值。 这如何应用于参数包? 认为 这可以在MSVC上编译,但不能在GCC和Clang上编译,请参见godbolt。这也

  • 这是在参数是重载函数时重载解析如何工作中提到的更复杂的问题? 下面的代码编译起来没有任何问题: 模板参数推导似乎不是一项具有挑战性的任务-只有一个函数接受两个参数。但是,取消注释的模板重载(仍然只有一个参数)会无缘无故地破坏编译。gcc 5. x/6. x和clang 3.9的编译都失败了。 它可以用重载解析/模板参数推导规则来解释,还是应该在这些编译器中被限定为缺陷?

  • 我正在尝试编写一个简单的模板,我可以使用该模板对带有单个参数的函数进行记忆: 但我得到了一个错误: 错误:没有匹配函数来调用“备忘录(双精度)” 注:候选人是: 注意:模板OUT记忆(IN) 注意:模板参数扣除/替换失败: 为什么编译失败? 实际上,当我指定所有模板参数时,我不明白为什么模板参数推导/替换会发生。 我使用的是gcc版本4.7.2(未启用C 11) PS:模板的错误比我最初意识到的要