C ++ 11:正确扩展尾随返回类型的模板参数包

问题描述 投票:0回答:1

我正在尝试使用switch语句在C ++ 11程序中将运行时常量转换为编译时常量。我有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交换分支中起作用,但在尾随返回类型中不起作用?

我可以通过将标准更改为C ++ 14并通过完全删除尾随返回类型来修复代码,但随后我将无法理解这里发生的情况。

我还尝试了不同的编译器(ICC,GCC,Clang),并且它们都给出了类似的错误消息,因此这里不能是编译器错误。

c++11 variadic-templates trailing-return-type
1个回答
0
投票

我不知道问题是什么,但是这种解决方法似乎正在起作用:

  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
© www.soinside.com 2019 - 2024. All rights reserved.