参数的重载函数(不)在编译时可推导
Overload function for arguments (not) deducable at compile time
有没有办法重载函数,以区分参数在编译时或仅在运行时可评估?
假设我有以下函数:
std::string lookup(int x) {
return table<x>::value;
}
这允许我根据恒定时间(带有空间开销)中的参数 x 选择一个字符串值。但是,在某些情况下,x
无法在编译时提供,我需要运行一个以更高的时间复杂度进行查找的 foo 版本。
当然,我可以使用具有不同名称的函数,但我希望有一个统一的接口。
我接受了答案,但我仍然对这种区别是否可以通过完全相同的函数调用进行感兴趣。
我相信
你能得到的最接近的是在int
和std::integral_constant<int>
上重载lookup
; 然后,如果调用者知道编译类型的值,他们可以调用后者重载:
#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
}
在线演示
笔记:
- 我在这里提供了一个
int_
帮助程序,因此std::integral_constant<int>
的构造对于调用者来说不那么冗长;这是可选的。 - 过载 c 将出现漏报(例如
constexpr int
变量被传递给重载 a,而不是重载 c),但这将清除任何实际的 int 文字。
一种选择是以类似的方式使用重载:
template <int x> std::string find() {
return table<x>::value;
}
std::string find(int x) {
return ...
}
还有这个技巧:
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);
}
当在编译时知道整数是有利的,但不是必需的时,这种事情效果很好。 例如,如果它有助于优化器。 不过,如果您以这种方式调用某些复杂函数的许多实例,那么编译时间可能会很糟糕。
相关文章:
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 错误:使用 clang 没有可行的重载,使用 GCC 编译
- 使用 MINGW gcc 编译时,不会为 std::string 调用重载的新运算符
- 编译以下重载<<需要什么enable_if或其他提示?
- C++编译时检查是否可以用某种类型的参数调用重载函数
- ostream 运算符的编译时重载
- 如何在C++编译时检查运算符的特定重载是否存在
- 简单的 SFINAE 示例以重载函数不编译
- 当其中一个函数未编译时,函数重载查找如何工作?
- 重载运算符编译错误?
- C++ - 在 std::thread 中调用重载函数时编译失败
- 如何重载 const 对象的 [],以便值赋值不会导致编译错误
- 使用 C++11 选项编译 C++98 代码时由于 Boost 标头而导致的不明确重载
- 编译错误:2 个重载没有'this'指针的合法转换。使用结构
- 线性重载:为什么 clang 在 GCC 编译时失败?
- C++运算符新重载、编译错误
- 在编译时推导具有未知类型的函数重载
- 使用 std::enable_if 的模板重载的隐式转换运算符 T() 无法编译
- 重载运算符时出现编译错误
- 运算符未编译'+'重载