【问题标题】:Static assertions about the size of a template struct关于模板结构大小的静态断言
【发布时间】:2017-06-20 17:13:57
【问题描述】:

我需要确保模板结构与其成员的大小完全相同。 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");
};

这不起作用。那么该怎么做呢?我不想让实例化模板的人在每次实例化中检查自己的负担。每当实例化结构时,检查应该是全自动的。

【问题讨论】:

  • 为什么不把static_assert 声明例如进入构造函数?
  • @πάνταῥεῖi 如果结构应该是 POD 类型,但它不能是默认构造函数。并且需要添加一个default默认构造函数。

标签: c++ templates sizeof static-assert


【解决方案1】:

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

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

这是因为成员函数的内容在类有一个完整的定义之前不会被编译。

无需调用该函数。

【讨论】:

  • "[C++14: 14.7.1/1]: [..] 类模板特化的隐式实例化导致声明的隐式实例化,而不是定义的隐式实例化、默认参数或异常规范类成员函数、成员类、作用域成员枚举、静态数据成员和成员模板; [..] "
  • "[C++14: 14.7.1/2]: 除非类模板或成员模板的成员已被显式实例化或显式特化,在引用特化时隐式实例化成员的特化在需要成员定义存在的上下文中; [..] "
  • 所以,是的,你必须调用它。
  • @LightnessRacesinOrbit 这看起来像是一个新的“谁的编译器错了”问题的提示:)
  • @LightnessRacesinOrbit 这是因为您的断言不依赖于模板类型。它既可以触发也可以不断言
【解决方案2】:

您可以添加一个图层:

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

【讨论】:

  • foo 本身在技术上是否不可能添加一些 [未使用] 字节,从而使断言的结果无效? Yakk 的type 成员想法解决了这个问题。
  • @LightnessRacesinOrbit:确实,除非bar&lt;T1, T2&gt; 具有标准布局。
【解决方案3】:

foo 重命名为foo_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;

请注意,在某些情况下使用foo 而不是foo_t 会阻止推理,因此这种技术并不完美。

【讨论】:

  • 哪些情况下扣费被屏蔽?
  • 我在这里提出了相同的解决方案stackoverflow.com/questions/42779120/…
  • @gio template&lt;class A, class B&gt; void deduction_no_worky( foo&lt;A,B&gt; const&amp;){} 然后foo&lt;int,char&gt; bob; deduction_no_worky(bob); 直接使用foo_t 就可以了。
  • 谢谢,这太疯狂了...std::is_same&lt;foo, foo_t&gt; 返回 true 但推论不起作用。
  • @GiovanniFunchal 是的,::type 的东西意味着这是一个非推断的上下文。为了使推论起作用,它必须能够反转任意图灵完备的过程(在一般情况下),因此 C++ 标准改为放置一条亮线。
猜你喜欢
  • 2016-07-17
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-27
  • 1970-01-01
相关资源
最近更新 更多