关于模板结构大小的静态断言

gex*_*ide 18 c++ templates sizeof static-assert

我需要确保模板结构与其成员的大小完全相同.static_assert似乎是这里的首选工具.但是,我不能static_assert在结构本身内部使用,因为那里的大小还不知道.这是我想要的:

template<typename T1,typename T2>
struct foo {
    T1 v1;
    T2 v2;
    // Doesn't compile, invalid application of sizeof to incomplete type
    static_assert(sizeof(foo<T1,T2>)==sizeof(T1)+sizeof(T2),"Struct size invalid");
};
Run Code Online (Sandbox Code Playgroud)

这不起作用.那怎么办呢?我不想让实例化模板的人在每个实例化中检查自己.只要实例化结构,检查应该是完全自动的.

Yak*_*ont 15

重命名foofoo_t.

template<class A, class B>
struct foo_helper {
  using type=foo_t<A,B>;
  static_assert(sizeof(A)+sizeof(B) == sizeof(type), "ouch");
};
template<class A, class B>
using foo=typename foo_helper<A,B>::type;
Run Code Online (Sandbox Code Playgroud)

请注意,在某些情况下使用foo而不是foo_t块扣除,所以这种技术并不完美.

  • @GiovanniFunchal是的,`:: type`东西意味着这是一个非推断的上下文.为了减少工作量,它必须能够反转任意的图灵完成过程(在一般情况下),所以C++标准代替了一条亮线. (2认同)

Jar*_*d42 9

您可以添加一个图层:

template<typename T1,typename T2>
struct bar {
    T1 v1;
    T2 v2;
};

template<typename T1,typename T2>
struct foo : bar<T1, T2> {
    static_assert(sizeof(bar<T1, T2>) == sizeof(T1) + sizeof(T2), "Struct size invalid");
};
Run Code Online (Sandbox Code Playgroud)

  • 从技术角度来说,`foo`本身是否可以添加一些[未使用的]字节,从而排除断言的结果?Yakk关于`type`成员的想法解决了这个问题. (4认同)

Ric*_*ges 5

将静态断言放在成员函数中.

template<typename T1,typename T2>
struct foo {
    T1 v1;
    T2 v2;

 static auto assertion()
 {
    static_assert(sizeof(foo<T1,T2>)==sizeof(T1)+sizeof(T2),"Struct size invalid");
 }
};
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为在类具有完整定义之前,不会编译成员函数的内容.

无需调用该功能.

  • _"`[C++ 14:14.7.1/1]:`_ [..] _**类模板特化的隐式实例化会导致声明的隐式实例化,但不会导致定义**,默认情况下类成员函数**,成员类,作用域成员枚举,静态数据成员和成员模板的参数或异常规范**; _ [..] _"_ (3认同)
  • _"`[C++ 14:14.7.1/2]:`除非已经显式实例化或明确专门化了类模板或成员模板的成员,否则当专门化时,会隐式实例化成员的特化.在需要成员定义存在的上下文中引用**; _ [..] _"_ (3认同)
  • 所以,是的,你必须打电话给它。 (2认同)
  • @LightnessRacesinOrbit这看起来像是一个新的"谁的编译器错误"的问题:) (2认同)
  • @LightnessRacesinOrbit因为你的断言不依赖于模板类型.它既可以解雇,也可以不断言 (2认同)
  • @RiaD:嗯.好的,但这与上面引用的14.7.1/1相符如何 (2认同)
  • 关于模板函数的规则"必须有一个有效的实例化"(如果我们假设模板类的成员在这个上下文中是模板函数)会使`static_assert(false,"hello")`形成错误,不需要诊断****.所以两个编译器都是正确的. (2认同)