C++11 C++;11可变模板类中的可变函数未按预期工作
真诚的道歉如果这已经在别处得到了答复,我确实搜索过了,但找不到明确的匹配项 我在模板类中有一个变量函数,它的工作方式与我预期的不完全一样。我有一个解决办法,但我怀疑这不是最好的解决办法 考虑以下代码:C++11 C++;11可变模板类中的可变函数未按预期工作,c++11,variadic-templates,variadic-functions,C++11,Variadic Templates,Variadic Functions,真诚的道歉如果这已经在别处得到了答复,我确实搜索过了,但找不到明确的匹配项 我在模板类中有一个变量函数,它的工作方式与我预期的不完全一样。我有一个解决办法,但我怀疑这不是最好的解决办法 考虑以下代码: #include <iostream> #include <functional> #include <vector> template< typename... ARGS > class Kitten { public: using Ca
#include <iostream>
#include <functional>
#include <vector>
template< typename... ARGS >
class Kitten
{
public:
using Callback = std::function< void( ARGS&&... ) >;
Kitten() = default;
void addCallback( Callback && c )
{
callbacks.push_back( std::forward< Callback >( c ) );
}
void processCallbacks( ARGS &&... args )
{
for ( Callback const &c : callbacks )
{
c( std::forward< ARGS >( args )... );
}
}
private:
std::vector< Callback > callbacks;
};
int main( int argc, const char * argv[] )
{
( void ) argc;
( void ) argv;
Kitten<int, float> kitty;
kitty.addCallback( []( int i, float f )
{
std::cout << "Int: " << i << "\nFloat: " << f << "\n";
} );
kitty.processCallbacks( 2, 3.141f );
int ii = 54;
float ff = 2.13f;
kitty.processCallbacks( ii, ff );
return 0;
}
关于评论中建议的使用std::move
的更改,addCallback
的形式似乎更加灵活:
template< typename FUNCTION >
void addCallback( FUNCTION && c )
{
callbacks.emplace_back( std::forward< FUNCTION >( c ) );
}
对于ARGS
中的每个类型,允许的值类别将由模板参数设置为Kitten
。例如,对于Kitten
,processCallbacks
将为第一个参数接受右值,为第二个参数接受左值(由于),为第三个参数接受两个(因为右值可以绑定到常量左值引用)。这不会给你完美的转发
template< typename... FORCEIT >
void processCallbacks( FORCEIT &&... args )
{
//...
}
模板
void processCallbacks(FORCEIT&&…args)
{
//...
}
该函数模板同时接受左值和右值,因为存在类型推断。这种参数称为转发参考参数。转发引用参数的形式必须为T&
,其中T
是一些推导的模板参数
如果您想要接受左值和右值并将它们完美地转发,那么应该使用后一种形式。虽然一开始你可能觉得奇怪,但这是一种相当常见的模式。你应该发布编译器错误。
std::forward(c)
等于std::move(c)
大概我也应该使用emplace\u back
来提高效率?@PiotrSkotnicki更新了我的问题(在底部)如果我的理解是正确的,那么现在可以使用std::forward
,而在原始版本中std::move
是合适的。@Slartibartfast如果Callback&&
是转发引用,那么使用std::forward
,如果它是右值引用,那么std::move
就足够了
error: rvalue reference to type 'int' cannot bind to lvalue of type 'int'
template< typename FUNCTION >
void addCallback( FUNCTION && c )
{
callbacks.emplace_back( std::forward< FUNCTION >( c ) );
}
std::function< void( int, float )> banana( []( int i, float f )
{
std::cout << "Int: " << i << "\nFloat: " << f << "\n";
} );
kitty.addCallback( banana );
void processCallbacks( ARGS &&... args )
{
//...
}
template< typename... FORCEIT >
void processCallbacks( FORCEIT &&... args )
{
//...
}