- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在CRTP ,我想干净利落地将构造函数注入(inject)派生类——不使用宏,也不写出来。这似乎是不可能的,所以我想出了一些解决方法。
首先,有一个基础 event class (QEvent)每个派生类 ( see rationale ) 应该有一个唯一的整数类型标签。您可以通过调用注册函数来获取它。创建一个 CRTP 包装器可以很容易地向您隐藏它:
template <typename Derived> class EventWrapper : public QEvent {
public:
EventWrapper() : QEvent(staticType()) {}
static QEvent::Type staticType() {
static QEvent::Type type = static_cast<QEvent::Type>(registerEventType());
return type;
}
};
class MyEvent1 : public EventWrapper<MyEvent1> {}; // easy-peasy
class MyEvent2 : public EventWrapper<MyEvent2> {};
请注意 MyEvent1::staticType() != MyEvent2::staticType()
: registerEventType()
每次调用时都会返回唯一的类型。
现在我想让事件类携带一些数据:
template <typename Derived> class StringEvent : public EventWrapper<D> {
std::string m_str;
public:
explicit StringEvent(const std::string & str) : m_str(str) {}
std::string value() const { return m_str; }
};
但是这里我们遇到了一个问题:我们需要在派生类的每个中手动定义构造函数。这里的重点是创建这样的类应该很容易,因为可能有许多不同的字符串携带事件类型。但这绝非易事:
class MyEvent3 : public StringEvent<MyEvent3> {
public: MyEvent3(std::string s) : StringEvent(s) {}
};
这显然很快就变老了,即使使用 C++11 构造函数转发也是如此:
class MyEvent3 : public StringEvent<MyEvent3> { using StringEvent::StringEvent; };
我们想要的是一种将此构造函数注入(inject)派生类的方法,或者避免这样做同时仍然提供易用性。当然,您可以将它隐藏在预处理器宏中,但我讨厌那些宏,因为它们为非常简单的概念引入了新名称,因此维护起来很麻烦。
我们当然可以使用虚拟类型。请注意,不需要定义虚拟类型。它只是用作类型参数的名称。
// Pre-C++11
class DummyEvent3;
typedef StringEvent<DummyEvent3> MyEvent3;
// C++11
class DummyEvent3;
using MyEvent3 = StringEvent<DummyEvent3>;
另一种解决方案是使用 int
模板参数并使用枚举值,但这带回了使用 registerEventType()
解决的唯一性问题第一名。保证大型程序的正确性可不是一件有趣的事。而且您仍然需要拼出枚举。
所以,我想出了一个元程序类,我将其称为元工厂,它可以为我们生成随时可用的 StringEvent
类,同时将它们全部保持为一种类型定义:
// the metafactory for string events
template <typename Derived> class StringEventMF {
public:
class Event : public EventWrapper<Derived> {
std::string m_str;
public:
explicit Event(const std::string & val) : m_str(val) {}
std::string value() const { return m_str; }
};
};
或者只是
template <typename Derived> class StringEventMF {
public:
typedef StringEvent<Derived> Event;
};
它的用法如下:
class Update : public StringEventMF<Update> {};
class Clear : public StringEventMF<Clear> {};
void test() {
Update::Event * ev = new Update::Event("foo");
...
}
您使用的类是 Update::Event
、Clear::Event
。 Update
和 Clear
是元工厂:它们为我们生成所需的事件类。从元工厂派生回避了从具体类类型派生。元工厂类型提供了创建独特具体类类型所需的独特类型鉴别器。
问题是:
是否有任何“更清洁”或“更理想”的方式来做这件事?理想情况下,以下无效伪代码将是我理想的实现方式 - 零重复:
class UpdateEvent : public StringEvent <magic>;
派生类的名称只出现一次,基本概念 StringEvent
的名称也只出现一次。 CRTP 要求类名出现两次 - 到目前为止我认为这是可以接受的,但我的元编程功能已经破烂不堪。同样,我想要一个无预处理器的解决方案,否则就很容易了。
metafactory 这个名字是我最初的发明(哈哈),还是仅仅是我的 google-Fu 所缺少的?这种元工厂模式似乎非常灵活。通过多重推导很容易组成元工厂。假设您想要一个工厂制作的 Update::Event
,另一个工厂制作的 Update::Foo
。
这个问题的动机是 this answer .注意:在实际代码中,我会使用 QString
,但我会尽量保持它的通用性。
最佳答案
我认为您正在寻找的可能只是使用 placement new 实例化基类。
派生类将不可构造,因为除非它们创建匹配的构造函数。
但是,它们不一定是可构建的,无论如何您都可以使用它们。 (它仍然可以被破坏)。
template <class T>
class Base
{
protected: Base(int blah) { }
public: static T* CreateInstance(int data) {
T* newOjectBlock = reinterpret_cast<T*>(::operator new(sizeof(T))); // allocate enough memory for the derived class
Base* newBasePlace = (Base*)(newOjectBlock); //point to the part that is reseved for the base class
newBasePlace= new ((char*)newBasePlace) Base(data); //call the placement new constrcutor for the base class
return newOjectBlock;
}
};
class Derived : public Base<Derived> {}
然后让CRTP基类这样构造派生类:
Derived* blah = Derived::CreateInstance(666);
如果有人想要初始化派生类,他们应该创建一个匹配的构造函数来调用基类构造函数。
或者,只需创建一个初始化其成员的 .init() 方法,并将在创建实例后调用。
或者,我们可以想别的东西,这只是一个概念的想法。
关于c++ - 有什么比元工厂更好的解决构造函数注入(inject)到 CRTP 中的派生类的问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19187469/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!