作者热门文章
- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
假设我有一个模板函数,它接受一个整数和一个对类型 T 实例的 const 引用。现在根据整数,只有一些 T 是可接受的,否则在运行时会抛出异常。
如果此函数的所有使用都使用常量整数,则可以将 int 设为模板参数并使用静态断言来检查它是否可接受。所以而不是 func(1,c)
一个人会使用 func<1>(c)
并将获得编译时类型检查。有没有办法写func(1,c)
并且仍然保持编译时检查,同时还能够编写 func(i,c)
并使用动态断言?目标是使其对开发人员透明。如果添加这种安全性而不用为编译时常量之类的事情打扰开发人员,那就太好了。他们可能只记得 func(1,c)
始终有效并使用它,避免检查。
如何尽可能使用静态断言定义函数,否则使用动态断言?
以下代码显示了 Ivan Shcherbakov 的 GCC 解决方案:
#include <iostream>
#include <cassert>
template<typename T>
void __attribute__((always_inline)) func(const int& i, const T& t);
void compile_time_error_() __attribute__((__error__ ("assertion failed")));
template<>
void __attribute__((always_inline))
func(const int& i, const float& t)
{
do {
if (i != 0) {
if (__builtin_constant_p(i)) compile_time_error_();
std::cerr << "assertion xzy failed" << std::endl;
exit(1);
}
} while (0);
func_impl<float>(i,t);
}
这将只允许 i=0 和 T=float 的组合。对于其他组合,一个好方法是创建一个生成代码 template<> func(const int& i, const T& t)
的宏。替换为 T 和 i != 0。
最佳答案
好吧,如果你使用的是 GCC,你可以使用一个肮脏的 hack,但它只有在启用函数内联(-O1 或更多)时才有效:
void my_error() __attribute__((__error__ ("Your message here")));
template <typename T1, typename T2> struct compare_types
{
enum {Equals = 0};
};
template <typename T1> struct compare_types<T1,T1>
{
enum {Equals = 1};
};
template <typename Type> __attribute__((always_inline)) void func(int a, Type &x)
{
if (__builtin_constant_p(a))
{
if (a == 1 && compare_types<Type,char>::Equals)
my_error();
}
}
在这种情况下,当 a == 1
且 Type
为 char
时,您将收到错误消息。这是一个将触发它的示例:
int main()
{
char x;
func(1, x);
return 0;
}
请注意,此示例严重依赖于特定于 gcc 的 __builtin_constant_p()
函数,无法与其他编译器一起使用!
关于c++ - 如果可能的话静态断言,否则动态断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11441302/
我是一名优秀的程序员,十分优秀!