我注意到奇怪的行为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) 我想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不起作用,因为我不能命名"编译器用于文字的类型".
我想知道std::enable_ifoverstatic_asserts防止模板实例化的优势。这个答案表明,这std::enable_if允许SFINAE,这在函数模板的情况下是一个令人信服的论点。
然而,这个论点对于类模板(和变量模板)是否合法?据我所知,那里不涉及重载决议,这使得 SFINAE - 再次,据我所知 - 不相关,但我可能是错的。如果是这样,你能举一个例子吗?
如果不是,我认为static_assert在类模板的情况下是给定问题(防止模板实例化)的更好解决方案,因为它可以说更明确、简洁和可读,并允许自定义错误消息。这是正确的还是我错过了 SFINAE 以外的一点?
请考虑以下 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) 我浏览了清单,std::type_traits但没有找到与std容器有关的任何内容。
我正在寻找std在编译时将容器传递给模板类型的方法。
template < typename T >
void foo( T bar )
{
static_assert( is_std_container??? );
}
Run Code Online (Sandbox Code Playgroud) 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之前一样根本不在那里. …
我想阻止调用某些函数.让我们忽略通过函数指针或其他东西调用函数的情况,只关注直接函数调用的情况.我可以这样做= delete.但是,所发布的诊断信息并不充分.我考虑过使用static_assert,您可以使用它来提供自定义诊断消息.我static_assert(false, ...)在函数体中放置了一个语句,希望在调用函数时它会触发.但是,事实证明static_assert即使没有调用该函数也会失败.有什么建议?
附加说明:该功能无条件禁止.所以,std::enable_if这里不适用.这样一个函数的动机是我想要阻止某些使用,否则可以通过重载解析来编译.所以我不能只删除该功能.deprecated不是我想要的.我想要编译错误,而不是警告.
说我有一些模板类:
template<class T>
class Foo{}
template<class T>
class Bar{}
Run Code Online (Sandbox Code Playgroud)
现在,我想确保(在编译时)使用的类型Bar派生自Foo.我已经找到了这个答案,展示了如何在运行时这样做,但我想在编译时检查,也许使用static_assert或者其他东西.
有没有办法做到这一点?
这是对另一个问题的后续行动
我试图在编译时建立一个特定的实现是否在结构中添加了未命名的填充.像gcc这样的特定实现允许使用pragma来控制结构中的填充和对齐,但代价是与其他实现的兼容性.由于这两个static_assert和offset_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所说:
在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.结构对象中可能存在未命名的填充,但不是在其开头.
我假设如果结构中元素的偏移量是在它之前声明的元素的大小的总和,那么这些元素之间不存在填充,并且它们应该连续分配,从而如果它们是相同类型则构成数组.
问题是:上述假设是错误的,它是(对参考问题的评论让我们思考)为什么?
static-assert ×10
c++ ×8
templates ×5
c ×2
c++11 ×2
compile-time ×1
enable-if ×1
gcc ×1
sfinae ×1
struct ×1
type-traits ×1