带有rvalue param调用的C++ 11模板化函数

tow*_*120 0 c++ templates rvalue-reference c++11

在某些O类中,我有模板化的函数test2:

struct A{int value;};

struct O{
    A value;

    template<typename Args>
    static void test2(Args &&args){
        std::cout << std::endl << "!!!" << std::is_rvalue_reference<decltype(args)>::value << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

比,我想从另一个调用此函数:

template<typename Args>
void test(Args &&args){
    using t = decltype(std::forward<Args>(args).value);
    std::cout << std::is_rvalue_reference<decltype(args)>::value;
    std::cout << std::is_rvalue_reference<decltype(std::forward<Args>(args).value)>::value;
    std::cout << std::is_rvalue_reference<t>::value;

    // All ok
    O.test2(std::forward<Args>(args).value);            

    // Alvays rvalue, even if agrs is lvalue
    O::template test2<t>(
        std::forward<t>(
            std::forward<Args>(args).value
        )
    );

   // Nor work at all, cant cast A to A&&
   O::template test2<t>(
        std::forward<Args>(args).value
    );
);

}
Run Code Online (Sandbox Code Playgroud)

http://coliru.stacked-crooked.com/a/3bbf040904845a54

如果我只是在std::forward<Args>(args).value没有指定模板类型的情况下传递,它会正确地推断出类型,但是如果我必须传递类型,我该如何调用函数呢?

似乎我不能正确地手动推断类型.


UPDATE

我需要明确指定参数,因为我有这样的函数(伪代码):

//initially call wind from somewhere.

// Tuple defined in class and is std::tuple
template<class Callback, class ...Args>
void wind(Tuple&& tuple, Callback &&callback){   
    using elementT = decltype(std::get<index>(std::forward<Tuple>(tuple)));

    ///
    /// !!! Problem here !!!
    ///
    callback.template operator()<elementT, Args...>(  std::get<index>(std::forward<Tuple>(tuple))  );              // std::get automatically return &/&&

   // recursivly call wind until the end
   wind<Callback, Args...>( std::forward<Tuple>(tuple), std::forward<Callback>(callback));
}

// callback looks like:
struct CallMe{   
  // Args provide type info. No function arguments here.
  template<class Data, class ...Args>
  void operator(Data &&data){

  }
}
Run Code Online (Sandbox Code Playgroud)

这个问题与调用wind和callback()函数有关.

Pra*_*ian 5

template<typename Args>
static void test2(Args&& args)
{ ... }
Run Code Online (Sandbox Code Playgroud)

在上面的函数中,即使参数类型看起来像一个右值引用,它也可以绑定到rvalue和lvalue参数.这通俗地称为通用参考.如果函数参数是类型的右值U,那么T推导为U,并且T&&U&&一个右值引用,这是直截了当的.但是,当函数参数是类型的左值时U,T则将推导为U&,这意味着函数参数类型将U& &&经历参考折叠变为U&.但是,要应用这些特殊规则,必须推断出类型.


O::test2(std::forward<Args>(args).value); // changed O.test2 to O::test2
Run Code Online (Sandbox Code Playgroud)

在这种情况下,模板参数类型是从函数参数推导出来的.参数本身是左值,因此函数参数的类型args也是左值.


O::template test2<t>(
    std::forward<t>(
        std::forward<Args>(args).value
    )
);
Run Code Online (Sandbox Code Playgroud)

这里的区别在于您已明确指定了模板参数类型test2.没有进行推论,在这种情况下,函数参数是一个简单的右值引用.它只能绑定到右值,并且由于外部强制转换std::forward<t>(此处t = A)而提供此右值.它具有相同的效果static_cast<A&&>(value).


O::template test2<t>(
    std::forward<Args>(args).value
);
Run Code Online (Sandbox Code Playgroud)

最后一个案例应该解释为什么这不起作用.如上所述,test2在这种情况下只能绑定到rvalue,而没有std::forward上面的第二个,你试图将左值绑定到一个rvalue引用参数,该参数失败.