c++11 - C++11:在尾随返回类型中正确扩展模板参数包
问题描述
我试图在我的 C++11 程序中使用switch
语句将运行时常量转换为编译时常量。我有enum SomeEnum {A, B, C};
,根据它的值我想调用模板函数f<A>()
,f<B>()
或者f<C>()
。我的代码中有很多依赖于SomeEnum
(以及其他模板参数)的模板函数,所以我决定制作专用dispatch
函数。这是我要编译的代码:
#include <utility>
enum SomeEnum {
A, B, C
};
template<template<SomeEnum, typename...> class FUNCTOR, typename ...OTHERS, typename ...ARGS> inline auto dispatch (
SomeEnum const type,
ARGS&&... args
) -> decltype( FUNCTOR<A, OTHERS...>::function(std::forward<ARGS>(args)...) ) { //Problem here
switch(type) {
case A:
return FUNCTOR<A, OTHERS...>::function(std::forward<ARGS>(args)...);
case B:
return FUNCTOR<B, OTHERS...>::function(std::forward<ARGS>(args)...);
case C:
return FUNCTOR<C, OTHERS...>::function(std::forward<ARGS>(args)...);
default:
//Do not call any function if enum value is wrong, just return something:
return decltype( FUNCTOR<A, OTHERS...>::function(std::forward<ARGS>(args)...) )();
}
}
template<SomeEnum T> struct TemplateFunctor1 {
static inline int function(int) { return 0; }
};
template<SomeEnum T, class OTHER> struct TemplateFunctor2 {
static inline int function(int) { return 0; }
};
int main(void) {
dispatch<TemplateFunctor1>(B, 0); //Problem here!
dispatch<TemplateFunctor2, int>(B, 0);
return 0;
}
(函数返回类型取决于模板参数的情况我不需要处理)
编译该行时出现错误dispatch<TemplateFunctor1>(B, 0);
,其中仅需要一个模板参数TemplateFunctor1
。错误消息如下:
error: no matching function for call to 'dispatch(SomeEnum, int)'
note: candidate: template<template<SomeEnum <anonymous>, class ...> class FUNCTOR, class ... OTHERS, class ... ARGS> decltype (FUNCTOR<(SomeEnum)0u, OTHERS ...>::function((forward<ARGS>)(dispatch::args)...)) dispatch(SomeEnum, ARGS&& ...)
note: template argument deduction/substitution failed
error: wrong number of template arguments (2, should be 1)
在这部分代码FUNCTOR<A, OTHERS...>
中:尾随返回类型。
所以我尝试将FUNCTOR<A, OTHERS...>
尾随返回类型更改为FUNCTOR<A>
,然后dispatch<TemplateFunctor2, int>(B, 0);
无法编译该行。它说我提供了错误数量的模板参数(1,应该是 2),这是一个相当预期的错误。
我在这里不明白的是为什么相同的decltype()
构造在default
switch 分支中有效,但在尾随返回类型中无效?
我可以通过将标准更改为 C++14 并完全删除尾随返回类型来修复我的代码,但是我不明白这里发生了什么。
我还尝试了不同的编译器(ICC、GCC、Clang),它们都给出了类似的错误消息,所以这里不可能是编译器错误。
解决方案
我不知道问题是什么,但这种解决方法似乎有效:
template <template<SomeEnum, typename...> class FUNCTOR, typename... X>
struct Wrapper
{
using Type = FUNCTOR<A, X...>;
};
template<template<SomeEnum, typename...> class FUNCTOR, typename ...OTHERS, typename ...ARGS>
inline auto dispatch (
SomeEnum const type,
ARGS&&... args
) -> decltype( Wrapper<FUNCTOR, OTHERS...>::Type::function(std::forward<ARGS>(args)...) ) { //No problem here
推荐阅读
- mysql - SQLAlchemy mysql 无法获取正确的字符集
- python - 在 django 中访问 sqlite3 中的异常线程
- python - OpenCV线检测python
- javascript - Javascript - 按多个值对对象进行排序
- javascript - 在 mssql 中使用各自的 id 更新多行和多列
- asp.net-mvc - 独立运行React Native,独立运行MVC时调用MVC动作方法
- laravel-8 - Laravel:使用模型查询构建器获取重复记录的结果
- windows - 在 Windows CMD 中的 for 循环后保存结果
- android-studio - Windows 10 格式设置为阿拉伯语或波斯语时的 Android Studio 服务器连接问题
- javascript - 是否可以映射到 src 中的文件夹?创建反应应用