代码之家  ›  专栏  ›  技术社区  ›  Rene

可变模板:整数参数到lambda的完美转发

  •  6
  • Rene  · 技术社区  · 7 年前

    也有类似的问题,但我没有找到一个适合我的问题的答案。

    考虑以下代码:

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

    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 回复  |  直到 7 年前
        1
  •  4
  •   Vittorio Romeo    7 年前

    这个 operator() 封闭式 由您的 lambda表达式 const -合格。 std::forward args... ,它们是闭包的数据成员。 无法移动对象。

    你可以把你的lambda标记为 mutable :

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

    这将删除隐式 常数 来自 封闭式 已生成 运算符() .

    live example on wandbox.org

        2
  •  7
  •   Rakete1111    7 年前

    args... const . 所以,如果你让你的lambda可变,那么它就起作用了:

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

    它不起作用的原因 decltype(args) 常数