传递variadic arg to模板函数时的汇编误差
Compilation error when passing variadic args to a template function
我有以下模板方法:
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;
});
}
本质上,我要做的就是将variadic Args
绑定到 T::create
(本身就是静态变异模板方法),但允许在称为时分别填充第一个参数(窗口)。
上面的代码失败,以下错误
error: no match for call to ‘(const std::_Bind<std::shared_ptr<{anonymous}::SceneWithArgs> (*(std::_Placeholder<1>, const char*))(smlt::Window*&, const char (&)[4])>) (smlt::Window*&)’
auto ret = func(window);
~~~~^~~~~~~~
这样调用代码时:
manager.register_scene<SceneWithArgs>("test", "arg");
我不太了解错误或如何解决。
我最初通过简单地调用lambda中的创建来解决此问题,这在GCC 4.9及更高版本上起作用,但是我必须与GCC 4.8.4保持兼容,并且有一个错误可以防止使用lambda内的variadic args:(
update
好的,添加std :: decay(如注释中所示)并未完全解决问题,第一个参数一直在推荐到Window*&&
而不是Window*
,但实际上指定了func
的类型(例如std::function<SceneBasePtr (Window*)>
),而不是使用auto
使事情编译。
我不确定为什么那是...
您没有显示create
的声明,但我认为它看起来如下:
template <typename... Args>
static SceneBasePtr create(Args&&...);
看起来不错。您使用转发引用,以便编译器可以推断出确切的参数类型。只要编译器推论类型,这将起作用。但是...
&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");
第一个是明确传递的,它是Window*
,这很明显。现在Args...
-"test"
和"arg"
是原始的字符串文字,它们的相应类型分别为const char[5]
和const char[4]
。然后Args...
(扣除过程后)成为const char(&)[5]
和const char(&)[4]
。那么,当您将create
与这些类型实例化时,现在会发生什么?您最终将获得以下声明:
static SceneBasePtr create(Window*&&, const char(&)[5], const char(&)[4]);
请注意,参考折叠规则将第一个参数转换为R值参考,其余的是L值参考。
std::bind
也推论类型。但是,std::bind
将需要存储参数,以便以后可以重复使用。问题是std::bind
无法存储const char[5]
。相反,它将 decay 每个参数的类型。这意味着每个原始字符串文字将成为const char*
,并将作为该类型的L值参数传递到绑定函数,并且这与手动实例化的create
不匹配。window
参数也是一个类似的问题。但是,它被推论为L值,但是,手动实例化的create
函数期望R值。
最好不要明确指定功能模板的模板类型。如果由于某些原因(错误?),您不能在lambda内使用args...
,则可以生成适当的create
签名:
&T::template create<Window*&, typename std::decay<Args>::type&...>
// ~^~ ~~~~~~~~~^
最终以:
static SceneBasePtr create(Window*&, const char*&, const char*&);
- 为什么在浮点中从大到小会引入更多的误差
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- 在 emscripten 网页汇编正在运行期间更新进度条?
- 为什么我们不编写可以处理C++标识符的汇编器和链接器?
- 在什么情况下,我想在 C/C++ 代码中使用内联汇编代码
- 为什么 memcpy() 和其他类似的函数使用汇编?
- [[可能]]和[[不太可能]]影响程序汇编的简单示例?
- 基于相邻元素 c++ 的分段误差范围的循环
- 在Cython中使用移动方法时的汇编误差
- typedef void汇编误差(是初始化的(使用dectType))
- C (MACOS)的汇编误差
- 使用C 中的constexpr汇编误差
- MSYS2上使用GCC 8.2.1的本本汇编误差
- 使用MPIC 误差进行C 汇编
- 传递variadic arg to模板函数时的汇编误差
- 汇编误差:从CSV转换为LIBSVM格式
- variadic模板递归返回类型扣除汇编误差
- 使用模板和lambda的汇编误差与clang
- Boost ::几何3D多边形交叉汇编误差
- 无序的一组对,汇编误差