c++ - 避免在 C++17 中为每个联合样式类编写构造函数
问题描述
我在一个项目中坚持使用 c++17,所以我无权访问指定的初始化程序。我有一堆联合类型,我想避免以这种方式初始化(因为它很烦人):
MyUnionType x;
x.value = value_set_for_all_union_members;
我想要这个
MyUnionType x(value_set_for_all_union_members);
但我也想避免为我创建的每个联合编写实现。我知道我所有的联合类型都将具有以下结构,每个联合都意味着实际上代表位字段,所以我实际上确实想要在这里进行类型修剪,我知道根据 C++ 它是“UB”,但是在 C++ 委员会中,在 C 中它不是未定义的行为,因此我关心的所有编译器都会在这里做我想做的事。
union Example{
integer_type value;
custom_safe_bitfield_abstraction<...> a;
custom_safe_bitfield_abstraction<...> b;
...
};
我想,好吧,我就继承构造函数,并使用 CRTP 提取适当的integer_type
. 当然我不能直接继承联合,所以我选择了这个策略:
struct Example : Base<Example>{
union{
integer_type value;
custom_safe_bitfield_abstraction<...> a;
custom_safe_bitfield_abstraction<...> b;
...
};
};
使用匿名联合,我应该能够以与以前相同的方式使用它(example.value 应该是联合内部的值)。
然后在实现中我执行以下操作:
template<class Derived_T>
struct Base{
using value_type = decltype(Derived_T::value);
explicit Base(value_type v){
static_cast<Derived_T*>(this)->value = v;
}
}
然而这不起作用:
error: Incomplete type 'Example' used in nested name specifier
> using value_type = decltype(Derived_T::value);
显然,我们不允许在声明成员之前引用它。好的...但是必须有某种方法可以将类型数据提取出来,毕竟我不关心任何内存对齐或任何事情。
我能想到的唯一另一件事是在 CRTP 模板参数(即Base<Derived_T, value_type>
)中包含类型,但我想避免这样做。我想有一些方法可以在每个派生类上编写函数或指定内部类型,我也不想这样做(并且有点违背了我正在做的事情的目的)。
有没有办法避免为每个类编写构造函数,并且不牺牲我拥有的其他代码重复最小化目标?
解决方案
不完全是你问的......但你可以使用你可以在成员函数内部使用类型的事实D::value
......所以在模板构造函数上使用 SFINAE......
我的意思是,你可以写一些东西
template <typename D>
struct Base
{
template <typename T>
static constexpr bool is_value_type ()
{ return std::is_same_v<decltype(D::value), T>; }
template <typename T, bool B = is_value_type<T>(),
std::enable_if_t<B, int> = 0>
explicit Base (T v)
{ static_cast<D*>(this)->value = v; }
};
仅当推导的参数类型与B::value
.
还记得添加using
using Base<Example>::Base;
里面Example
。
下面是一个完整的编译示例
#include <type_traits>
template <typename D>
struct Base
{
template <typename T>
static constexpr bool is_value_type ()
{ return std::is_same_v<decltype(D::value), T>; }
template <typename T, bool B = is_value_type<T>(),
std::enable_if_t<B, int> = 0>
explicit Base (T v)
{ static_cast<D*>(this)->value = v; }
};
struct Example : Base<Example>
{
using Base<Example>::Base;
union
{
long value;
long a;
long b;
};
};
int main ()
{
//Example e0{0}; // compilation error
Example e1{1l}; // compile
//Example e2{2ll}; // compilation error
}
推荐阅读
- sql - SSIS 数据质量控制方法
- python - 我怎样才能让所有的背景移动而不是只移动一个平台?
- c# - 发布/订阅消息在生产中丢失
- javascript - Typescript 接口中的输入类型
- jquery - jQueryEasyUI:如何重新加载组合网格?
- python - 如果每个数字旁边都有一个字符串,我如何使用此代码查找文件中的前 5 个最大数字?
- laravel - Laravel Nova - 范围关系字段
- bash - kafka-console-producer:找不到命令
- javascript - 在 vue.js 中呈现应用程序之前加载微调器
- r - 如何在 geom_boxplot 中定义我自己的陷波间隔?