我正在寻找一种在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
来模拟这个,但无法找到一种方法来强制只接受文字参数。有没有办法做到这一点?
答案 0 :(得分:31)
这是一个可移植的C ++ 11解决方案,因此您的函数(实际上是宏,抱歉)只接受整数文字并触发编译时错误:
constexpr int operator "" _literal(unsigned long long i)
{
return i;
}
#define m_builtin_foo(integer) builtin_foo(integer ## _literal)
用户定义的文字只接受文字(因此他们的名字)。因此,如果您将宏的用户定义文字粘贴到传递给它的内容,则 只接受相应用户定义文字所接受的文字。
然而,这相当丑陋,我想这可能容易出错。不知道怎么回事。
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))
这当然会接受任何整数常量表达式,而不仅仅是文字。