如何判断参数何时来自硬编码?

时间:2015-12-10 15:47:19

标签: c++ templates parameter-passing overloading

我希望能够判断传递给函数,方法或类方法的数字参数是否来自硬编码。

所以,例如调用

MyFunc(2);

int a = 1;
MyFunc(a);

应该重载函数以允许不同的实现或某种区分方式

void MyFunc(int num)
{
  if (isHardcodedNumber(num))
    doThis();
  else
    doThat();
}

这是一个简化版本。理想情况下,我需要一个采用模板参数的解决方案,适用于任何内置数值类型。

这可能吗?

4 个答案:

答案 0 :(得分:3)

你无法区分这两种情况。

您的函数只是在堆栈上(或在寄存器中,取决于您的处理器)获取一个值。

无法 知道该值在被推入堆栈或复制到寄存器之前来自何处(当然,除非您传递额外的参数来指示左右)。

答案 1 :(得分:3)

实际上,我可以考虑实现它的极端丑陋的黑客攻击。但请不要......这只是为了学术讨论。

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);

模板专家可能会将其转换为编译时常量,但我不会走得那么远。

但无论如何,请不要在第一时间。

答案 2 :(得分:2)

你可以排序通过重载rvalue引用来做到这一点,尽管这会阻止你拥有一个值版本(因为它变得模棱两可):

#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

请在此处查看:http://ideone.com/gZoD3m

答案 3 :(得分:2)

好吧,正如其他人所说的那样 - 不建议这样做,但只是为了表明它在某种程度上是可能的,但我不确定它是否适用于所有情况:

首先,您应该知道 - 您可以测试是否在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不被视为const。所以,似乎是错误的方式。

但是...

您可以使用模板标记调度和宏 - 来使某些工作正常:

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);
    }
};

宏定义 - 当然 - 你总是有相同的args:

#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被称为......

     好吧,我不是constexpr f()

     

非constexpr被召唤,我猜......

     

7

     

1