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 )
{
    //...
}