0

我试图在我的 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()构造在defaultswitch 分支中有效,但在尾随返回类型中无效?

我可以通过将标准更改为 C++14 并完全删除尾随返回类型来修复我的代码,但是我不明白这里发生了什么。

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

4

1 回答 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
于 2020-05-27T06:38:06.367 回答