如何判断参数何时来自硬编码数字?
How to tell when an argument is from a hardcoded number?
我希望能够判断传递给函数、方法或 class 方法的数字参数是否来自硬编码数字。
例如打电话
MyFunc(2);
或
int a = 1;
MyFunc(a);
应该重载函数以允许不同的实现或某种区分方式
void MyFunc(int num)
{
if (isHardcodedNumber(num))
doThis();
else
doThat();
}
这是简化版。理想情况下,我需要一个采用模板参数并适用于任何内置数字类型的解决方案。
这可能吗?
你分不清这两种情况。
您的函数只是获取传递给它的堆栈上(或寄存器中,取决于您的处理器)的值。
它无法知道该值在被压入堆栈或复制到寄存器之前来自哪里(除非,当然,你传递了一个额外的参数来表示如此)。
你可以有点通过重载右值引用来做到这一点,尽管这会阻止你拥有值版本(因为它变得模棱两可):
#include <iostream>
using namespace std;
void f(int&& f)
{
std::cout << "r-value reference: " << f << '\n';
}
void f(const int& f)
{
std::cout << "value: " << f << '\n';
}
// you can't have void f(int) as it is now ambiguous.
int main()
{
f(1);
int a = 2;
f(a);
// it can be fooled though
f(std::move(a));
return 0;
}
打印:
r-value reference: 1
value: 2
r-value reference: 2
实际上,我可以想出一个极其丑陋的 hack 来实现它。但请不要.. 这仅供学术讨论。
bool isNumber(const char* x){
return isdigit(x[0]);
}
#define MyFunc_t(x) MyFunc(x,#x)
void MyFunc(int x , const char* xStr){
bool isHardcodedNumber = isNumber(xStr);
//do...
}
MyFunc_t(4);
int x = 8;
MyFunc_t(x);
模板专家也许可以将其转换为编译时常量,但我不会走那么远。
但无论如何,请不要放在第一位。
好吧,正如其他人所说 - 不建议这样做,只是为了表明它在某种程度上是可能的,但我不确定它是否适用于所有情况:
首先,您应该知道 - 您可以测试函数是否在 constexpr 上下文中被调用。只需检查其 noexcept
属性 - 如 here.
所述
所以,你可以测试:
constexpr int f_constexpr(int a)
{
return a;
}
int main(int argc, char* argv[])
{
cout << noexcept(f_constexpr(7)) << endl; // print 1
cout << noexcept(f_constexpr(argc)) << endl; // print 0
}
你得到 1
,然后从上面的这个程序中得到 0
。
不幸的是,在 f_constexpr(int)
正文中你总是得到 false
- 因为参数 a
不被视为常量。所以,似乎是错误的方式。
但是..
您可以使用模板标签分派和宏 - 来实现某些功能:
template <bool isConstexpr>
struct f_impl;
template <>
struct f_impl<false>
{
static int f(int a)
{
cout << "well, I'm not constexpr f()\n";
return a;
}
};
constexpr int f_constexpr(int a)
{
return a;
}
template <>
struct f_impl<true>
{
static constexpr int f(int a)
{
return f_constexpr(a);
}
};
和宏定义 - 可以肯定 - 你总是有相同的参数:
#define f(a) f_impl<noexcept(f_constexpr(a))>::f(a)
因此,只需检查它是否有效:
int main(int argc, char* argv[]) {
constexpr int a = f(7);
cout << "constexpr was called..." << endl;
int c = f(argc);
cout << "non constexpr was called, I guess..." << endl;
cout << a << endl;
cout << c << endl;
}
和live demo并输出:
constexpr was called...
well, I'm not constexpr f()
non constexpr was called, I guess...
7
1
我希望能够判断传递给函数、方法或 class 方法的数字参数是否来自硬编码数字。
例如打电话
MyFunc(2);
或
int a = 1;
MyFunc(a);
应该重载函数以允许不同的实现或某种区分方式
void MyFunc(int num)
{
if (isHardcodedNumber(num))
doThis();
else
doThat();
}
这是简化版。理想情况下,我需要一个采用模板参数并适用于任何内置数字类型的解决方案。
这可能吗?
你分不清这两种情况。
您的函数只是获取传递给它的堆栈上(或寄存器中,取决于您的处理器)的值。
它无法知道该值在被压入堆栈或复制到寄存器之前来自哪里(除非,当然,你传递了一个额外的参数来表示如此)。
你可以有点通过重载右值引用来做到这一点,尽管这会阻止你拥有值版本(因为它变得模棱两可):
#include <iostream>
using namespace std;
void f(int&& f)
{
std::cout << "r-value reference: " << f << '\n';
}
void f(const int& f)
{
std::cout << "value: " << f << '\n';
}
// you can't have void f(int) as it is now ambiguous.
int main()
{
f(1);
int a = 2;
f(a);
// it can be fooled though
f(std::move(a));
return 0;
}
打印:
r-value reference: 1
value: 2
r-value reference: 2
实际上,我可以想出一个极其丑陋的 hack 来实现它。但请不要.. 这仅供学术讨论。
bool isNumber(const char* x){
return isdigit(x[0]);
}
#define MyFunc_t(x) MyFunc(x,#x)
void MyFunc(int x , const char* xStr){
bool isHardcodedNumber = isNumber(xStr);
//do...
}
MyFunc_t(4);
int x = 8;
MyFunc_t(x);
模板专家也许可以将其转换为编译时常量,但我不会走那么远。
但无论如何,请不要放在第一位。
好吧,正如其他人所说 - 不建议这样做,只是为了表明它在某种程度上是可能的,但我不确定它是否适用于所有情况:
首先,您应该知道 - 您可以测试函数是否在 constexpr 上下文中被调用。只需检查其 noexcept
属性 - 如 here.
所以,你可以测试:
constexpr int f_constexpr(int a)
{
return a;
}
int main(int argc, char* argv[])
{
cout << noexcept(f_constexpr(7)) << endl; // print 1
cout << noexcept(f_constexpr(argc)) << endl; // print 0
}
你得到 1
,然后从上面的这个程序中得到 0
。
不幸的是,在 f_constexpr(int)
正文中你总是得到 false
- 因为参数 a
不被视为常量。所以,似乎是错误的方式。
但是..
您可以使用模板标签分派和宏 - 来实现某些功能:
template <bool isConstexpr>
struct f_impl;
template <>
struct f_impl<false>
{
static int f(int a)
{
cout << "well, I'm not constexpr f()\n";
return a;
}
};
constexpr int f_constexpr(int a)
{
return a;
}
template <>
struct f_impl<true>
{
static constexpr int f(int a)
{
return f_constexpr(a);
}
};
和宏定义 - 可以肯定 - 你总是有相同的参数:
#define f(a) f_impl<noexcept(f_constexpr(a))>::f(a)
因此,只需检查它是否有效:
int main(int argc, char* argv[]) {
constexpr int a = f(7);
cout << "constexpr was called..." << endl;
int c = f(argc);
cout << "non constexpr was called, I guess..." << endl;
cout << a << endl;
cout << c << endl;
}
和live demo并输出:
constexpr was called...
well, I'm not constexpr f()
non constexpr was called, I guess...
7
1