如果可能,静态断言,否则动态断言? [英] Static assertion if possible, dynamic assertion otherwise?

查看:100
本文介绍了如果可能,静态断言,否则动态断言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个模板函数,它接受一个整数和一个常量引用一个T类型的实例。现在根据整数,只有一些T是可以接受的,否则在运行时抛出一个异常。



如果此函数的所有使用都使用常量整数,那么可以使int为模板参数,并使用静态断言检查是否可接受。因此,代替 func(1,c),将使用 func< 1>(c)时间类型检查。有任何方法写 func(1,c)并仍然保持编译时检查,同时也能写 func 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)));

模板<>
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<>解决方案

好吧,如果你使用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 类型 char ,您会得到一个错误。下面是一个触发它的例子:

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

注意,这个例子很大程度上依赖于gcc-specific __ builtin_constant_p()函数,并且不能与其他编译器配合使用!


Let's say I have a template function that takes an integer and a const reference to an instance of type T. Now depending on the integer, only some T's are acceptible, otherwise an exception is thrown at runtime.

If all uses of this function would use constant integers, it would be possible to make the int a template parameter and use a static assertion to check if it is acceptable. So instead of func(1,c) one would use func<1>(c) and would gain compile-time type checking. Is there any way to write func(1,c) and still keep the compile-time check, while also being able to write func(i,c) and use a dynamic assertion? The goal is to make it transparent to the developer. It would simply be great to add this safety without bothering the developers about things like compile-time constants. They'd probably only remember that func(1,c) always works and use that, avoiding the check.

How can I define a function with a static assertion whenever possible and a dynamic assertion otherwise?


The following code shows the solution for GCC by Ivan Shcherbakov:

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

This will only allow the combination of i=0 and T=float. For other combinations a good way would be creating a Macro that produces the code of template<> func(const int& i, const T& t) with T and i != 0 replaced.

解决方案

Well, if you're using GCC, you can use a dirty hack, but it will only work when function inlining is enabled (-O1 or more):

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

In this case when a == 1 and Type is char, you'll get an error. Here's an example that will trigger it:

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

Note that this example heavily relies on the gcc-specific __builtin_constant_p() function and won't work with other compilers!

这篇关于如果可能,静态断言,否则动态断言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆