Static 断言实例化时模板类型的大小

Static assert the size of a template type on instantiation

提问人:plasmacel 提问时间:3/30/2016 最后编辑:plasmacel 更新时间:3/14/2019 访问量:1755

问:

我想在实例化时检查以下结构的大小,以约束未命名的紧密打包,因此的大小等效于 。static_assertstructAsizeof(T) * 3

template <typename T>
struct A
{
   union
   {
      struct { T a, b, c; };
      T arr[3];
   };
};

这可以通过以下方式完成

static_assert(sizeof(A<T>) == sizeof(T) * 3, "hey something went wrong");

然而

  • 由于在其类定义中仍然是一个不完整的类型,因此将上述内容放入类定义中不是一个选项A<T>static_assert

  • static_assertwith 不会在所有编译器(如 Clang)中计算未实例化的函数,因此将其放入虚拟成员函数中不是一种选择sizeof

  • 使用构造函数或析构函数将是一个解决方案,但是在上面的示例中不存在用户定义的构造函数(考虑聚合),此外,想象一下多个构造函数的情况,我将避免在所有构造函数中执行断言static_assert

  • 从另一个结构体继承,并在 的定义中执行它将是一个解决方案,但我想保持结构简单,而不会弄乱帮助程序结构Astatic_assertA

我错过了任何其他解决方案吗?

我决定取消删除这个问题,并保持开放状态,以便将来可能的解决方案。

C++ 模板 static-assert

评论

0赞 SomeWittyUsername 3/30/2016
当然,在 incomlete 类型上是不允许的,但是当你实例化你的结构时,类型不能是不完整的,否则它根本无法编译,无论有没有sizeofTsizeof
0赞 OMGtechy 3/30/2016
在不知道类型大小的情况下,无法创建联合,因此无论如何都需要完整的类型。所以,第一个解决方案应该没问题。
1赞 Jarod42 3/30/2016
仍然有析构函数,但(至于构造函数)您可能会破坏某些属性(聚合,微不足道的可破坏)。您必须启用移动/复制构造函数/赋值。
0赞 plasmacel 3/30/2016
@OMGtechy 否,类定义中的类 A 仍然不完整,因此第一个解决方案将无法编译。
0赞 plasmacel 3/30/2016
@SomeWittyUsername是的,但没有人谈论 T 是不完整的。A<T> 在其类定义中。

答:

0赞 ecatmur 3/30/2016 #1

一个保证被实例化的特殊成员函数(几乎)是析构函数:

~A() noexcept { static_assert(sizeof(A<T>) == sizeof(T) * 3, "hey something went wrong"); }

评论

1赞 plasmacel 3/30/2016
是的,但正如@Jarod42在他的评论中所说,这将破坏聚合规则并微不足道地默认可破坏性。
0赞 Red.Wave 3/14/2019 #2
namespace my_private_impl{
    struct impl_tag{};
    template <typename T,typename tag>
    struct A_impl{
        static_assert(is_same<tag,impl_tag>{}(),"you evil cheater");
        union{
            struct { T a, b, c; };
            T arr[3];
        };
    };
};

template<typename T>
using A=std::enable_if_t<
    sizeof(my_private_impl::A_impl<T,my_private_impl::impl_tag>) == sizeof(T) * 3,
    my_private_impl::A_impl<T,my_private_impl::impl_tag>
>;