变长模板:将整数参数完美转发到lambda函数

6

有类似的问题,但我没有找到适用于我的问题的答案。

考虑以下代码:

#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <utility>

class TestClass
{
public:
   TestClass( int value): mValue( value) { }
private:
   int  mValue;
};

template< typename T> class DeferredCreator
{
public:
   template< class... Args> DeferredCreator( Args&&... args):
      mpCreator( [=]() -> T*
         { return new T( std::forward< Args>( args)...);  }
      ),
      mpObject()
   { }

   T* get() {
      if (mpObject == nullptr)
         mpObject.reset( mpCreator());
      return mpObject.get();
   }
private:
   std::function< T*( void)>  mpCreator;
   std::unique_ptr< T>        mpObject;
};


int main() {
   DeferredCreator< int>  dcInt( 42);

   assert( dcInt.get() != nullptr);
   return 0;
}

这个思路是,当需要时类“DeferredCreator”才创建对象。我已经成功将其应用在字符串上,但我不知道如何将一个简单的整数传递到我的lambda表达式中。

我收到的错误信息是:

prog.cpp:19:26: error: no matching function for call to 'forward'
         { return new T( std::forward< Args>( args)...);  }
                         ^~~~~~~~~~~~~~~~~~~
prog.cpp:36:27: note: in instantiation of function template specialization 'DeferredCreator<int>::DeferredCreator<int>' requested here
   DeferredCreator< int>  dcInt( 42);
                          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/move.h:76:5: note: candidate function not viable: 1st argument ('const int') would lose const qualifier
    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/move.h:87:5: note: candidate function not viable: 1st argument ('const int') would lose const qualifier
    forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
    ^
2 errors generated.

我已经尝试将decltype(args)用作std::forward<>的模板参数,但那并没有帮助。

这段代码在这里也可以找到:https://ideone.com/MIhMkt

2个回答

8

args...是常量,因为lambda的调用运算符隐式为const。因此,如果您使您的lambda可变,那么它就可以工作:

[=]() mutable -> T*
     { return new T( std::forward< Args>( args)...);  }

它不能与 decltype(args) 一起工作的原因是类型本身并不是 const,只有调用操作符是。

4
你的lambda表达式生成的闭包类型operator()const修饰。 std::forward 可以尝试移动闭包的数据成员args...,但是const对象无法移动。
你可以将lambda标记为mutable:
  mpCreator( [=]() mutable -> T*
     { return new T( std::forward< Args>( args)...);  }
  ),

这将从闭包类型生成的 operator() 中移除隐式的 const 限定符。

wandbox.org上的实时示例


1
这里的 forward<Args>(args)... 真的会转发吗? - David G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接