标准库中聚合可初始化性的类型特征?

2024-04-18

C++标准库有std::is_constructible<Class, T...> http://en.cppreference.com/w/cpp/types/is_constructible检查是否可以从给定类型作为参数构造一个类。

例如,如果我有一堂课MyClass它有一个构造函数MyClass(int, char), then std::is_constructible<MyClass, int, char>::valuetrue.

是否有类似的标准库类型特征可以检查聚合初始化是否有效,即MyClass{int, char}格式良好并返回MyClass?

我的用例:

我想编写一个函数模板来转换std::tuple使用聚合初始化的(通常是 POD)类,具有以下签名:

template <typename Class, typename... T>
inline Class to_struct(std::tuple<T...>&& tp);

为了防止用户以无效的方式使用该功能Class,我可以写一个static_assert在此函数内检查是否给定tp参数具有可转换为成员的类型Class。这似乎是一种类型特征is_aggregate_initializable<Class, T...>会派上用场的。

我可以推出自己的此特征的实现,但仅供参考,标准库中是否存在我忽略的这样的特征,或者即将成为标准库的一部分的特征?


从评论中的讨论和浏览 C++ 参考来看,似乎没有聚合可初始化性和列表可初始化性的标准库类型特征,至少达到 C++17。

评论中强调,两者之间存在区别列表可初始化性 http://en.cppreference.com/w/cpp/language/list_initialization一般来说 (Class{arg1, arg2, ...}) and 聚合可初始化性 http://en.cppreference.com/w/cpp/language/aggregate_initialization.

列表可初始化性(具体来说direct列表可初始化性)更容易为其编写类型特征,因为该特征仅依赖于某种语法的有效性。对于我测试是否可以从元组的元素构造结构的用例,直接列表可初始化性似乎更合适。

实现此特征的可能方法(使用适当的 SFINAE)如下:

namespace detail {
    template <typename Struct, typename = void, typename... T>
    struct is_direct_list_initializable_impl : std::false_type {};

    template <typename Struct, typename... T>
    struct is_direct_list_initializable_impl<Struct, std::void_t<decltype(Struct{ std::declval<T>()... })>, T...> : std::true_type {};
}

template <typename Struct, typename... T>
using is_direct_list_initializable = detail::is_direct_list_initializable_impl<Struct, void, T...>;

template<typename Struct, typename... T>
constexpr bool is_direct_list_initializable_v = is_direct_list_initializable<Struct, T...>::value;

然后我们可以通过执行以下操作来测试直接列表的可初始化性is_direct_list_initializable_v<Class, T...>.

这也适用于移动语义和完美转发,因为std::declval遵守完善的转发规则。

聚合可初始化性不太简单,但有一个解决方案可以涵盖大多数情况。聚合初始化要求被初始化的类型是聚合(请参阅关于有关聚合初始化的 C++ 参考 http://en.cppreference.com/w/cpp/language/aggregate_initialization),我们有一个 C++17 特征std::is_aggregate http://en.cppreference.com/w/cpp/types/is_aggregate检查类型是否是聚合。

但是,这并不意味着仅仅因为类型是聚合,通常的直接列表初始化就会无效。仍然允许与构造函数匹配的正常列表初始化。例如,以下编译:

struct point {
    int x,y;
};

int main() {
    point e1{8}; // aggregate initialization :)
    point e2{e1}; // this is not aggregate initialization!
}

为了禁止这种列表初始化,我们可以利用聚合不能具有自定义(即用户提供的)构造函数这一事实,因此非聚合初始化必须只有一个参数,并且Class{arg}会满足std::is_same_v<Class, std::decay_t<decltype(arg)>>.

幸运的是,我们不能拥有与其封闭类相同类型的成员变量 https://stackoverflow.com/questions/4941629/why-cant-we-declare-object-of-a-class-inside-the-same-class,因此以下内容无效:

struct point {
    point x;
};

对此有一个警告:允许对同一对象的引用类型,因为成员引用可以是不完整的类型(GCC、Clang 和 MSVC 都接受这一点,没有任何警告):

struct point {
    point& x;
};

虽然不寻常,该代码根据标准有效 https://stackoverflow.com/questions/22098834/class-that-holds-a-reference-to-itself。我没有解决方案来检测这种情况并确定point可以使用类型的对象进行聚合初始化point&.

忽略上面的警告(很少需要使用这种类型),我们可以设计一个可行的解决方案:

template <typename Struct, typename... T>
using is_aggregate_initializable = std::conjunction<std::is_aggregate<Struct>, is_direct_list_initializable<Struct, T...>, std::negation<std::conjunction<std::bool_constant<sizeof...(T) == 1>, std::is_same<std::decay_t<std::tuple_element_t<0, std::tuple<T...>>>, Struct>>>>;

template<typename Struct, typename... T>
constexpr bool is_aggregate_initializable_v = is_aggregate_initializable<Struct, T...>::value;

它看起来不太好,但功能符合预期。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

标准库中聚合可初始化性的类型特征? 的相关文章

  • 在 Web 浏览器中禁用 F5 [重复]

    这个问题在这里已经有答案了 可能的重复 禁用浏览器的后退按钮 https stackoverflow com questions 961188 disable browsers back button 如何禁用浏览器上的 F5 刷新 htt
  • 从 Invoke 方法获取 RETURN

    我正在尝试从另一个线程上的列表框项目中读取值 我尝试创建一种新方法来运行调用命令 我可以设法将命令发送到列表框 例如通过调用方法添加 但我似乎无法得到响应 我似乎无法获取该项目的值 我尝试了几种方法 一旦我将它从空变为字符串 事情就开始变得
  • C# 和月历,选择多个日期

    我正在制作一个程序 可以帮助人们用 C 为某个部门 预订 订单 他们需要能够选择不同月份的多个日期 我更愿意拥有它 这样他们就可以单击一个日期 然后按住 Shift 键单击另一个日期以选择这两个日期之间的所有日期 并控制单击以进行单选 取消
  • 如何使用 C# 以编程方式编辑 Power BI Desktop 文档参数或数据源?

    我有一个在 Power BI Desktop 中内置的报告模板 并保存为 pbix 或 pbit 文件 该模板使用DirectQuery SQL数据库作为数据源 而服务器地址和数据库名称被提取到参数中 还有一个参数包含一个ReportId
  • C# Outlook 从收件人获取 CompanyName 属性

    我目前正在使用 C 编写 Outlook 2010 AddIn 我想要的是从我从 AppointmentItem 中提取的 Recipient 对象中获取 CompanyName 属性 因此 有了 AppointmentItem 的收件人
  • C++中的类要具备什么条件才能成为容器?

    我是 C 编程新手 偶然发现了这个术语containers举例如下vector deque map etc 一个企业的最低要求应该是什么class应该满足被称为container in C 我将从 范围 这个概念开始 Range 只有两个方
  • PrivateObject 找不到属性

    我的结构基本上如下所示 abstract class A protected string Identificator get set private void DoSomething DoSomethingSpecific protect
  • 提升mapped_file_source、对齐方式和页面大小

    我正在尝试在性能很重要的上下文中解析一些大小高达几百兆字节的文本文件 因此我使用 boostmapped file source 解析器期望源以空字节终止 因此我想检查文件大小是否是页面大小的精确倍数 如果是 则使用较慢的非内存映射方法 我
  • 检测 TextBox 中的 Tab 键按下

    I am trying to detect the Tab key press in a TextBox I know that the Tab key does not trigger the KeyDown KeyUp or the K
  • 如何在新窗口中打开图像或pdf文件?

    我有一个 gridview 它包含文件名和文件路径 图像和 pdf 格式文件 其中我使用了模板字段 在该字段下放置了 1 个图像按钮 单击该图像按钮 即 查看 按钮 时 我想在新窗口中打开所选文件 这是我的代码 protected void
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • MSChart 控件中的自定义 X/Y 网格线

    我有一个带有简单 2D 折线图的 C Windows 窗体 我想向其中添加自定义 X 或 Y 轴标记 并绘制自定义网格线 例如 以突出显示的颜色 虚线 我查看了 customLabels 属性 但这似乎覆盖了我仍然想显示的默认网格 这是为了
  • 用数组或向量实现多维数组

    我想使用单个数组或向量实现多维数组 可以像通常的多维数组一样访问它 例如 a 1 2 3 我陷入困境的是如何实施 操作员 如果数组的维数为 1 则 a 1 应该返回位于索引 1 处的元素 但是如果维数大于一怎么办 对于嵌套向量 例如 3 维
  • 与 Entity Framework Core 2.0 的一对零关系

    我正在使用 C 和 NET Framework 4 7 将 Entity Framework 6 1 3 Code First 库迁移到 Entity Framework Core 我一直在用 Google 搜索 Entity Framew
  • 解释这段代码的工作原理;子进程如何返回值以及在哪里返回值?

    我不明白子进程如何返回该值以及返回给谁 输出为 6 7 问题来源 http www cs utexas edu mwalfish classes s11 cs372h hw sol1 html http www cs utexas edu
  • 值和类型的简洁双向静态 1:1 映射

    我将从我想象如何使用我想要创建的代码开始 它不必完全像这样 但它是我在标题中所说的 简洁 的一个很好的例子 就我而言 它是将类型映射到相关的枚举值 struct bar foo
  • 使用 IdentityDbContext 和 Code First 自动迁移表位置和架构的实体框架?

    我正在尝试使用 IdentityDbContext 类设置自动迁移更新 并将更改传播到整个数据库的实际 DbContext 在进入代码之前 在使用自动迁移实现 IdentityDbContext 时 我收到此错误 影响迁移历史系统表位置的自
  • 对多个对象使用事件处理程序

    我有 20 件物品List
  • MSVC编译器下使用最大成员初始化联合

    我正在尝试初始化一个LARGE INTEGER在 C 库中为 0 确切地说是 C 03 以前 初始化是 static LARGE INTEGER freq 0 在 MinGW 下它产生了一个警告 缺少成员 LARGE INTEGER Hig
  • 运行 xunit 测试时无法将输出打印到控制台窗口

    public class test2InAnotherProject private readonly ITestOutputHelper output public test2InAnotherProject ITestOutputHel

随机推荐