【问题标题】:Working around the static type property of C++解决 C++ 的静态类型属性
【发布时间】:2015-05-29 13:34:07
【问题描述】:

考虑这段代码

template<typename T>
void call_me(const T& arg) {
}

template<int i>
struct custom_type {
};


void foo(int i)
{
  switch (i) {
  case 0:
    call_me( custom_type<0>() );
    break;
  case 1:
    call_me( custom_type<1>() );
    break;
  case 2:
    call_me( custom_type<2>() );
    break;
  default:
    break;
  }
}

switch 语句的用途是不完整的,也就是说,它适用于所有整数,而不仅仅是上面明确提到的少数整数。 C++ 不允许像custom_type&lt;i&gt; 这样的语句,因为i 不是常量表达式。 (..我不能将函数 foo 的参数更改为常量表达式)。此外,我不想使用外部代码生成器来生成巨大的 switch 语句并将其反馈到源代码中..

在 C++/11/14/17 中是否有任何方法允许以优雅的方式编写对 call_me 的函数调用,或者答案只是“不,C++ 是静态类型的。”?

【问题讨论】:

  • 这是不可能的,因为函数参数i是在运行时确定的。但是,如果您解释了您要与这些人一起解决的实际问题,也许会想出一些好主意。
  • 如果i在编译时是未知的,应该是构造函数参数,而不是模板参数

标签: c++


【解决方案1】:

这样的东西应该可以工作,加上特殊情况 call_me_t

template <int N>
struct call_me_t
{
   static void exec(int i)
   {
       if (i < N)
           call_me_t<N-1>::exec(i) ;
       else if (i == N)
           call_me(custom_type<N>()) ;
   }
} ;

template<>
struct call_me_t<0>
{
   static void exec(int i)
   {
     call_me(custom_type<0>()) ;
   }
};


void foo(int i)
{
    call_me_t<10>::exec(i) ; // 10 is maximum value in switch
}

【讨论】:

  • 递归使用数值模板常量是个好主意
  • 它在这种形式下不起作用,因为i&lt;N 检查是运行时检查。所以编译器将永远不会停止生成越来越多的嵌套版本。我想如果您为案例N==0 添加模板特化,然后递归停止并且它是可行的。
  • 这实际上有效 `template struct call_me_t { static void exec(int i) { call_me(custom_type()); } };
  • 是的,你需要一个特殊的 call_me_t 来停止递归。顺便说一句,在这种情况下,函数模板应该可以完成这项工作。我从结构开始,因为不能做偏函数模板专业化,但是这里没有偏...
  • 对不起。我只是看到你已经在文中提到了这一点。没看到。
【解决方案2】:

您可以使用以下内容:

template <std::size_t I>
void call_me_with_custom_type()
{
    call_me(custom_type<I>());
}

namespace detail
{

    template <std::size_t ... Is>
    void foo(std::index_sequence<Is...>, int i)
    {
        std::function<void()> calls[] = {call_me_with_custom_type<Is>...};

        calls[i]();
    }

}

template <std::size_t N>
void foo(int i)
{
    detail::foo(std::make_index_sequence<N>{}, i);
}

【讨论】:

  • 我需要一些时间来解决这个问题。现在,我认为这是一个非常优雅的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
相关资源
最近更新 更多