Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将可变参数传递给模板函数时出现编译错误_C++_C++11_Templates_Bind_Variadic Templates - Fatal编程技术网

C++ 将可变参数传递给模板函数时出现编译错误

C++ 将可变参数传递给模板函数时出现编译错误,c++,c++11,templates,bind,variadic-templates,C++,C++11,Templates,Bind,Variadic Templates,我有以下模板方法: template<typename T, typename... Args> void register_scene(const std::string& name, Args&&... args) { auto func = std::bind(&T::template create<Window*, Args&...>, std::placeholders::_1, std::forward<A

我有以下模板方法:

template<typename T, typename... Args>
void register_scene(const std::string& name, Args&&... args) {
    auto func = std::bind(&T::template create<Window*, Args&...>, std::placeholders::_1, std::forward<Args>(args)...);

    _store_scene_factory(name, [=](Window* window) -> SceneBasePtr {
        auto ret = func(window);
        ret->set_name(name);
        return ret;
    });
}
像这样调用代码时:

manager.register_scene<SceneWithArgs>("test", "arg");
manager.register_场景(“测试”、“参数”);
我真的不明白这个错误,也不知道如何修复它

我最初通过在lambda内部调用create解决了这个问题,这在GCC 4.9及以上版本中有效,但我必须与GCC 4.8.4兼容,并且存在一个错误,它阻止在lambda内部使用可变参数:(

更新

好的,因此添加std::decay(如注释中所示)并不能完全解决问题,第一个参数一直在推导
Window*&&
,而不是
Window*
,但实际上指定了
func
的类型(例如
std::function
),而不是使用
auto
,从而使事情得以编译


我不知道为什么…

您没有显示
create
的声明,但我假设它如下所示:

template <typename... Args>
static SceneBasePtr create(Args&&...);
请注意,引用折叠规则将第一个参数转换为r值引用,而其余参数为l值引用

std::bind
也会推断类型。但是,
std::bind
会希望存储参数,以便以后可以重用。问题是
std::bind
无法存储
const char[5]
。相反,它将衰减每个参数的类型。这意味着每个原始字符串文字将成为
const char*
,并将作为此类型的l值参数传递给绑定函数,这与手动实例化的
create
不匹配。
窗口
参数也存在类似问题。它被推断为l值,但是,手动实例化的
create
函数需要r值

最好不要明确指定函数模板的模板类型。如果由于某些原因(错误?)无法在lambda中使用
args…
,则可以生成适当的
创建
签名:

&T::template create<Window*&, typename std::decay<Args>::type&...>
//                        ~^~          ~~~~~~~~~^  

您可能需要将
create
转换为
create
 &T::template create<Window*, Args&...>
template <typename T, typename... Args>
void register_scene(const std::string& name, Args&&... args);
//...
manager.register_scene<SceneWithArgs>("test", "arg");
static SceneBasePtr create(Window*&&, const char(&)[5], const char(&)[4]);
&T::template create<Window*&, typename std::decay<Args>::type&...>
//                        ~^~          ~~~~~~~~~^  
static SceneBasePtr create(Window*&, const char*&, const char*&);