标签: static-assert

为什么模板中的static_assert给出了不同的结果和等价的表达式?

我注意到奇怪的行为static_assert:

#include <iostream>

template <typename T, unsigned int D> struct Vec
{
    static_assert(D && 0, "Invalid dimension for vector!");
};

template <typename T> struct Vec<T, 1>             {union {T x, r;};};
template <typename T> struct Vec<T, 2> : Vec<T, 1> {union {T y, g;};};
template <typename T> struct Vec<T, 3> : Vec<T, 2> {union {T z, b;};};
template <typename T> struct Vec<T, 4> : Vec<T, 3> {union {T w, a;};};

int main()
{
    Vec<float, 3> v;
    v.x = 1; …
Run Code Online (Sandbox Code Playgroud)

c++ gcc templates static-assert

3
推荐指数
1
解决办法
384
查看次数

static_assert宽字符文字的签名?

我想static_assert()广泛的字符文字(L'x')的签名与wchar_t.

定义wchar_t是我自己的.(我正在实现一个C标准库.)如果用户使用的编译器对宽字符签名的概念与库中配置的不同,我想尽早失败,大声失败.

断言匹配大小的类型很容易:

static_assert( sizeof( wchar_t ) == sizeof( L'x' ), "size matches" );
Run Code Online (Sandbox Code Playgroud)

对于内置类型char,测试签名很容易.假设在_CHAR_IS_SIGNED某处定义为0或1,

static_assert( ( (char)-1 < 0 ) == _CHAR_IS_SIGNED, "char is signed" );
Run Code Online (Sandbox Code Playgroud)

诀窍.

但是,wchar_t不是一个内置式...

有没有办法在"纯"C99或C11中进行此(静态)断言,即不依赖于特定编译器的扩展?


澄清:

我"是"图书馆.我必须要typedef一些整数类型wchar_t.

编译器 - 不是我 - 将宽字符文字定义为某种类型.编译器为此类型指定名称,但理想情况下应与我使用的任何名称相同wchar_t,包括签名(其中,AFAICT,未由标准指定).

我想以某种方式断言/测试这些类型的身份.上面(type)-1 < 0显示的检查char不起作用,因为我不能命名"编译器用于文字的类型".

c static-assert

3
推荐指数
1
解决办法
169
查看次数

对于类模板,std::enable_if 相对于 static_assert 的优势是什么?

我想知道std::enable_ifoverstatic_asserts防止模板实例化的优势。这个答案表明,这std::enable_if允许SFINAE,这在函数模板的情况下是一个令人信服的论点。

然而,这个论点对于类模板(和变量模板)是否合法?据我所知,那里不涉及重载决议,这使得 SFINAE - 再次,据我所知 - 不相关,但我可能是错的。如果是这样,你能举一个例子吗?

如果不是,我认为static_assert在类模板的情况下是给定问题(防止模板实例化)的更好解决方案,因为它可以说更明确、简洁和可读,并允许自定义错误消息。这是正确的还是我错过了 SFINAE 以外的一点?

c++ templates static-assert enable-if class-template

3
推荐指数
1
解决办法
193
查看次数

为什么 static_assert 会破坏替换?

请考虑以下 C++14 代码:

#include <type_traits>

template<typename T>
class Bar {
    static_assert(std::is_destructible<T>::value, "T must be destructible");
};

template<typename T>
void foo(Bar<T> const &) {}

template<typename T>
void foo(T const &) {}

class Product {
public:
    static Product *createProduct() { return new Product{}; }
    static void destroyProduct(Product *product) { delete product; }
private:
    Product() = default;
    ~Product() = default;
};

int main()
{
    Product* p = Product::createProduct();
   
    foo(*p);            // call 1: works fine
    foo<Product>(*p);   // call 2: fails to compile
       
    Product::destroyProduct(p);
           
    return …
Run Code Online (Sandbox Code Playgroud)

c++ static-assert sfinae

3
推荐指数
1
解决办法
105
查看次数

标准容器的type_traits?

我浏览了清单,std::type_traits但没有找到与std容器有关的任何内容。

我正在寻找std在编译时将容器传递给模板类型的方法。

template < typename T >
void foo( T bar )
{
    static_assert( is_std_container??? );
}
Run Code Online (Sandbox Code Playgroud)

c++ templates static-assert type-traits c++11

2
推荐指数
2
解决办法
2839
查看次数

我可以禁用静态断言吗?

static_assert我的代码中散布着一些相当昂贵的电话.虽然它们很有价值,但它们通常非常丰富,并且对编译时间和内存使用有很大贡献.

我可以禁用它们吗?

c++ static-assert

2
推荐指数
1
解决办法
1082
查看次数

如何设置一个评估static_assert的前提条件?

我有这个函数用于零覆盖的东西,它使用static_assert检查给定的东西的类型是否是POD类型:

template <bool safeMode = true, typename generic>
void overwriteWithZeros( generic *variableAddress )
{
    if (safeMode) static_assert(std::is_pod<generic>::value, "Only POD types can be properly overwriten");

    const size_t size = sizeof(generic);
    unsigned char *variableData = (unsigned char*)(variableAddress);

    for (size_t i = 0; i < size; i++)
        variableData[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)

我在这里打电话:

int main()
{
    being *creature = new being(100, "a guinea pig"); // being is not a POD type

    overwriteWithZeros<false>(creature);
    // totally unrelated stuff...
}
Run Code Online (Sandbox Code Playgroud)

因为它safeMode是一个编译时的值,我不知道为什么它会发生它是真的或者它是假的,static_assert总是"发生",给我当时预期的错误,因为being它不是POD类型,就像if在static_assert之前一样根本不在那里. …

c++ templates static-assert

2
推荐指数
1
解决办法
90
查看次数

用`static_assert`禁止函数

我想阻止调用某些函数.让我们忽略通过函数指针或其他东西调用函数的情况,只关注直接函数调用的情况.我可以这样做= delete.但是,所发布的诊断信息并不充分.我考虑过使用static_assert,您可以使用它来提供自定义诊断消息.我static_assert(false, ...)在函数体中放置了一个语句,希望在调用函数时它会触发.但是,事实证明static_assert即使没有调用该函数也会失败.有什么建议?

附加说明:该功能无条件禁止.所以,std::enable_if这里不适用.这样一个函数的动机是我想要阻止某些使用,否则可以通过重载解析来编译.所以我不能只删除该功能.deprecated不是我想要的.我想要编译错误,而不是警告.

c++ static-assert compile-time deleted-functions c++11

2
推荐指数
1
解决办法
1908
查看次数

如何确定类型是否在编译时从模板类派生?

说我有一些模板类:

template<class T>
class Foo{}

template<class T>
class Bar{}
Run Code Online (Sandbox Code Playgroud)

现在,我想确保(在编译时)使用的类型Bar派生自Foo.我已经找到了这个答案,展示了如何在运行时这样做,但我想在编译时检查,也许使用static_assert或者其他东西.
有没有办法做到这一点?

c++ templates static-assert

2
推荐指数
1
解决办法
78
查看次数

我们可以使用static_assert来检测结构中的填充吗?

这是对另一个问题的后续行动

我试图在编译时建立一个特定的实现是否在结构中添加了未命名的填充.像gcc这样的特定实现允许使用pragma来控制结构中的填充和对齐,但代价是与其他实现的兼容性.由于这两个static_assertoffset_of被用于C11的n1570草案所要求的,我想用他们看到实现是否成员之间使用填充.

这是代码的相关部分(引用问题中的完整代码):

#include <stdio.h>
#include <stddef.h>
#include <assert.h>

struct quad {
    int x;
    int y;
    int z;
    int t;
};

int main() {
    // ensure members are consecutive (note 1)
    static_assert(offsetof(struct quad, t) == 3 * sizeof(int),
        "unexpected padding in quad struct");
    struct quad q;
    ...
Run Code Online (Sandbox Code Playgroud)

正如6.7.2.1结构和联合说明符§15所说:

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.结构对象中可能存在未命名的填充,但不是在其开头.

我假设如果结构中元素的偏移量是在它之前声明的元素的大小的总和,那么这些元素之间不存在填充,并且它们应该连续分配,从而如果它们是相同类型则构成数组.

问题是:上述假设是错误的,它是(对参考问题的评论让我们思考)为什么?

c struct static-assert

2
推荐指数
1
解决办法
613
查看次数