如何解决避免在 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),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
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。