【问题标题】:Overload function for arguments (not) deducable at compile time编译时可推导的参数(不可)的重载函数
【发布时间】:2016-01-14 14:58:09
【问题描述】:

有没有办法重载函数以区分参数在编译时或仅在运行时可评估?

假设我有以下功能:

 std::string lookup(int x) {
     return table<x>::value;
 }

它允许我在恒定时间内根据参数 x 选择一个字符串值(有空间开销)。但是,在某些情况下,x 无法在编译时提供,我需要运行一个 foo 版本,它会以更高的时间复杂度进行查找。

我当然可以使用不同名称的函数,但我希望有一个统一的接口。


我接受了一个答案,但我仍然对完全相同的函数调用是否可以实现这种区别感兴趣。

【问题讨论】:

  • 不幸的是,根据您的编辑,this question 的答案将显示“否”。如果有方法,我一定会很想知道!

标签: c++ c++11 overloading


【解决方案1】:

我相信你能得到的最接近的方法是在intstd::integral_constant&lt;int&gt; 上重载lookup;然后,如果调用者知道 compile-type 的值,他们可以调用后者的重载:

#include <type_traits>
#include <string>

std::string lookup(int const& x)                   // a
{
    return "a"; // high-complexity lookup using x
}

template<int x>
std::string lookup(std::integral_constant<int, x>) // b
{
    return "b"; // return table<x>::value;
}

template<typename T = void>
void lookup(int const&&)                           // c
{
    static_assert(
        !std::is_same<T, T>{},
        "to pass a compile-time constant to lookup, pass"
         " an instance of std::integral_constant<int>"
    );
}

template<int N>
using int_ = std::integral_constant<int, N>;

int main()
{
    int x = 3;
    int const y = 3;
    constexpr int z = 3;
    lookup(x);         // calls a
    lookup(y);         // calls a
    lookup(z);         // calls a
    lookup(int_<3>{}); // calls b
    lookup(3);         // calls c, compile-time error
}

Online Demo

注意事项:

  • 我在这里提供了一个int_ 助手,所以std::integral_constant&lt;int&gt; 的构造对于调用者来说不那么冗长;这是可选的。
  • 重载 c 会产生误报(例如,constexpr int 变量被传递给重载 a,而不是重载 c),但这会清除任何实际的 int 字面量。

【讨论】:

    【解决方案2】:

    一种选择是以类似的方式使用重载:

    template <int x> std::string find() {
       return table<x>::value;
    }
    
    std::string find(int x) {
        return ...
    }    
    

    【讨论】:

      【解决方案3】:

      还有这个技巧:

      std::string lookup(int x) {
          switch(x) {
          case 0: return table<0>::value;
          case 1: return table<1>::value;
          case 2: return table<2>::value;
          case 3: return table<3>::value;
          default: return generic_lookup(x);
      }
      

      当整数在编译时已知是有利的但不是必需的,这种事情很有效。例如,如果它有助于优化器。但是,如果您以这种方式调用一些复杂函数的许多实例,那么编译时间可能会很糟糕。

      【讨论】:

        猜你喜欢
        • 2021-10-12
        • 2017-12-10
        • 2019-03-08
        • 1970-01-01
        • 1970-01-01
        • 2021-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多