只接受文字整数的函数

时间:2015-03-12 11:04:23

标签: c++

我正在寻找一种在C ++中模拟某些重载GCC内置函数的方法。内置插件与以下内容类似:

__builtin_foo(char *a, signed int b);
__builtin_foo(short *a, signed int b);
__builtin_foo(long *a, signed int b);

在GCC中使用硬编码的特殊限制:b必须是字面值,即您可以调用:

__builtin_foo((char *)0, 1);

但不是:

extern int val;
__builtin_foo((char *)0, val);

生成编译器错误。我已经摆弄std::enable_if来模拟这个,但无法找到一种方法来强制只接受文字参数。有没有办法做到这一点?

3 个答案:

答案 0 :(得分:31)

这是一个可移植的C ++ 11解决方案,因此您的函数(实际上是宏,抱歉)只接受整数文字并触发编译时错误:

constexpr int operator "" _literal(unsigned long long i)
{
    return i;
}

#define m_builtin_foo(integer) builtin_foo(integer ## _literal)

用户定义的文字只接受文字(因此他们的名字)。因此,如果您将宏的用户定义文字粘贴到传递给它的内容,则 只接受相应用户定义文字所接受的文字。

然而,这相当丑陋,我想这可能容易出错。不知道怎么回事。


@MichaelAnderson在评论中指出m_builtin_foo(i+1)仍然可行。那是对的。 @Angew建议在一个与整数运算不兼容的包装器中包装返回类型_literal并添加显式转换。他也是对的,这是更完整的解决方案:

struct wrapper
{
    constexpr wrapper(int n):
        value{n}
    {}

    explicit constexpr operator int() const
    {
        return value;
    }

    int value;
};

constexpr wrapper operator "" _literal(unsigned long long i)
{
    return { int(i) };
}

#define m_builtin_foo(integer) builtin_foo(int(integer ## _literal))

答案 1 :(得分:15)

您可以使用宏和GCC内在__builtin_constant_p

对其进行模拟
constexpr int foo(int i) { return i; }

#define FOO(i) do { \
  static_assert(__builtin_constant_p(i), "Not a constant"); \
  foo(i); \
} while (false)

这将允许FOO(1)编译,但不允许int i = 1; FOO(i);

但是,__builtin_constant_p的结果取决于优化级别,在更高级别的优化const变量被视为常量,因此它不仅接受文字。

当然,如果你愿意允许常量表达式而不仅仅是文字,那么你所要做的就是在需要常量表达式的上下文中使用变量,例如静态断言或非类型模板参数。

答案 2 :(得分:13)

您可以将该功能转换为模板:

template <int b>
builtin_foo(char *a);

调用语法将为builtin_foo<1>(whatever)

如果您不喜欢这样,可以将模板包装在宏中:

#define m_builtin_foo(a, b) builtin_foo<(b)>((a))

这当然会接受任何整数常量表达式,而不仅仅是文字。