微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 如果可能,静态断言,否则动态断言?

假设我有一个模板函数,它使用一个整数和一个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的组合.对于其他组合,一个好的方法是创建一个生成模板代码的宏,更换T和i!= 0的func(const int& i,const T& t)

解决方法

那么,如果你使用GCC,你可以使用一个脏的黑客,但是只有在启用函数内联(-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();
    }
}

在这种情况下,当一个== 1和Type是char时,你会得到一个错误.这是一个会触发它的例子:

int main()
{
    char x;
    func(1,x);
    return 0;
}

请注意,此示例严重依赖于gcc特定的__builtin_constant_p()函数,并且不能与其他编译器一起使用!

原文地址:https://www.jb51.cc/c/112525.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐