C++ 避免在C+中编写每个联合样式类的构造函数+;17
我在一个项目中使用c++17,所以我无法访问指定的初始值设定项。我有很多联合类型,我希望避免以这种方式初始化(因为这很烦人): 我想要这个C++ 避免在C+中编写每个联合样式类的构造函数+;17,c++,templates,c++17,unions,crtp,C++,Templates,C++17,Unions,Crtp,我在一个项目中使用c++17,所以我无法访问指定的初始值设定项。我有很多联合类型,我希望避免以这种方式初始化(因为这很烦人): 我想要这个 MyUnionType x(value_set_for_all_union_members); 但我也希望避免为我创建的每个联合编写实现。我知道我所有的联合类型都将有以下结构,每个联盟都是实际表示比特字段的,所以我实际上希望在这里进行类型修剪,我知道它是根据C++的“ub”,但是在C++委员会上,在C中它不是未定义的行为,因此,我关心的所有编译器都将在这
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;
...
};
使用匿名联合,我应该能够像以前一样使用它(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;
}
}
显然,我们不允许在声明之前引用成员。可以但必须有某种方法来提取类型数据,毕竟我不关心任何内存对齐或任何事情
我唯一能想到的另一件事是在CRTP模板参数中包含类型(即Base
),但我希望避免这样做。我想象有一种方法可以在每个派生类上编写函数或指定内部类型,我也不想这样做(这有点违背了我所做的目的)
有没有一种方法可以避免在不牺牲我的其他代码重复最小化目标的情况下,为每个类编写构造函数?不完全是您所要求的。。。但是您可以使用这样一个事实,即您可以在成员函数中使用
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; }
};
内部示例
下面是一个完整的编译示例
#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
}
#包括
模板
结构基
{
模板
静态constexpr bool是\u值\u类型()
{return std::is_same_v;}
模板
显式基(tV)
{static_cast(this)->value=v;}
};
结构示例:Base
{
使用Base::Base;
联盟
{
长期价值;
长a;
长b;
};
};
int main()
{
//示例e0{0};//编译错误
示例e1{1l};//编译
//示例e2{2ll};//编译错误
}
不完全是你要求的。。。但是您可以使用这样一个事实,即您可以在成员函数中使用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; }
};
内部示例
下面是一个完整的编译示例
#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
}
#包括
模板
结构基
{
模板
静态constexpr bool是\u值\u类型()
{return std::is_same_v;}
模板
显式基(tV)
{static_cast(this)->value=v;}
};
结构示例:Base
{
使用Base::Base;
联盟
{
长期价值;
长a;
长b;
};
};
int main()
{
//示例e0{0};//编译错误
示例e1{1l};//编译
//示例e2{2ll};//编译错误
}
我认为可以使用模板函数而不是继承。工厂function@GaryNLOL你能详细说明一下吗?我想我仍然有“需要从模板中找到成员变量的类型”的问题。FWIW,通过一个联合类型的惩罚是C++中的非法行为。我还没见过一个编译器不能达到大多数人的期望,但你在UB的土地上。根据您实际执行的操作/需要,a是一种类型安全的联合类型,您可以使用。@NathanOliver我需要类型修剪,因为我通过它们实现安全位字段,我不试图存储互斥类型。我认为您可以使用模板函数而不是继承。工厂function@GaryNLOL你能详细说明一下吗?我想我仍然有“需要从模板中找到成员变量的类型”的问题。FWIW,通过一个联合类型的惩罚是C++中的非法行为。我还没见过一个编译器不能达到大多数人的期望,但你在UB的土地上。根据您实际执行的操作/需要,a是一种类型安全的联合类型,您可以使用。@NathanOliver我需要类型修剪,因为我通过它们实现了安全的位字段,我没有试图存储互斥的类型。我认为这正是我要寻找的,至少在我的用例中,还请注意,使用Base::Base代码>代替Base::Base工作代码>也是。我感到困惑的是,为什么会这样。为什么这样做会成功,同时使用子级值的decltype,而直接获取该类型的尝试失败了?这仅仅是因为类本身的定义不再依赖于特定的类型或其他什么吗?@hythis-类的某一点是,您不完全知道(“不完整类型”)模板参数是如何生成的(例如:如果有一个值
成员或该成员的类型)。因此,decltype(D::value)
在方法体内部工作,但不能使用它来构造方法本身的签名。我相信存在一些未定义的行为,因为对象是从最基本的顺序构造到最派生的顺序,因此,访问基
构造函数中的值
就是访问尚未构造的对象的成员变量。也许在实践中不会有任何问题,但需要注意的是,我认为这正是我所要寻找的,至少对于我的用例来说,还要注意,使用Base::Base代码>代替Base::Base工作代码>也是。我感到困惑的是,为什么会这样。为什么这样做会成功,同时使用子级值的decltype,而直接获取该类型的尝试失败了?这仅仅是因为类本身的定义不再依赖于特定的类型或其他什么吗?@hythis-类的某一点是,你不完全知道(“不完整类型”)模板是如何定义的
using Base<Example>::Base;
#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
}