混合层和混合层静态绑定

发布于 2024-11-16 01:17:13 字数 2827 浏览 1 评论 0 原文

我目前正在玩 mixin 层设计,并且我被困住了 烦人的问题。 让我们考虑以下基本 mixin 层:

template <typename Next> 
struct Layer1 : public Next 
{ 
 struct A : public Next::A 
 { 
   void f() { g(); } 
   void g() {} 
 }; 
};

这里没有什么花哨的,只是一个带有 2 个方法 f()g() 方法的简单 mixin。 请注意,来自 f()g() 调用静态绑定到此 具体的Layer1::A::g()。 现在,我想要的是能够完全挂钩这个方法 mixin 来实现,比如说,一个日志层:

template <typename Next> 
struct Layer2 : public Next 
{ 
 struct A : public Next::A 
 { 
   void f() 
   { 
     std::cout << "Layer2::A::f() [enter]" << std::endl; 
     Next::A::f(); 
     std::cout << "Layer2::A::f() [leave]" << std::endl; 
   } 
   void g() 
   { 
     std::cout << "Layer2::A::g() [enter]" << std::endl; 
     Next::A::g(); 
     std::cout << "Layer2::A::g() [leave]" << std::endl; 
   } 
 }; 
};

考虑到Layer2>,这里的问题是任何调用 Layer2 之上的层中的 f()g() 将正确向下级联到 Layer2::A::g(),从而显示正确的日志消息。但 从 Layer2 下面调用 f()g() 将不会记录任何内容,因为 该调用将静态绑定到可用的 g() 拨打电话的时间。 这意味着从 Layer2 之上的任何层调用 f() 显然会 仍然总是从 Layer1::A::f() 调用 Layer1::A::g() 并且不显示 日志消息。 我想出了两个解决这个问题的方法:

  1. 虚拟性:显然不可接受。 mixin 层的要点 就是在没有必要的时候避免虚拟。

  2. 向图层添加模板参数以提供先前的 层,类似的东西。

template <typename Next, template <typename> class Prev> 
struct Layer2 : public Next 
{ 
 typedef Next next_t; 
 struct A : public Next::A 
 { 
   void f() 
   { 
     std::cout << "Layer2::A::f() [enter]" << std::endl; 
     Next::A::f(); 
     std::cout << "Layer2::A::f() [leave]" << std::endl; 
   } 
   void g() 
   { 
     std::cout << "Layer2::A::g() [enter]" << std::endl; 
     Next::A::g(); 
     std::cout << "Layer2::A::g() [leave]" << std::endl; 
   } 
 }; 
}; 

template <typename Next, template <typename> class Prev> 
struct Layer1 : public Next 
{ 
 typedef Next next_t; 
 struct A : public Next::A 
 { 
   void f() 
   { 
     std::cout << "Layer1::A::f() [enter]" << std::endl; 
     ((typename Prev<Layer1<Next,Prev> >::A*)this)->g(); 
     std::cout << "Layer1::A::f() [leave]" << std::endl; 
   } 
   void g() 
   { 
     std::cout << "Layer1::A::g() [enter]" << std::endl; 
     std::cout << "Layer1::A::g() [leave]" << std::endl; 
   } 
 }; 
}; 

typedef Layer2<Layer1<Layer0,Layer2>,NullType> Application;

嗯,它有效,但我想隐藏第二个模板 参数,因为它是多余的。 想问一下大家有没有遇到过这样的问题,是怎么解决的 由于明显缺乏,您是否开发了解决方案来解决它 有关 mixin 层的文章。

I'm currently playing with mixin layers designs, and I'm stuck with an
annoying problem.
Let's consider the following basic mixin layer:

template <typename Next> 
struct Layer1 : public Next 
{ 
 struct A : public Next::A 
 { 
   void f() { g(); } 
   void g() {} 
 }; 
};

Nothing fancy here, just a simple mixin with 2 methods f() and g().
Notice that the g() call from f() is is statically binded to this
specific Layer1::A::g().
Now, what I want is to be able to completely hook the methods of this
mixin to implement, say, a logging layer:

template <typename Next> 
struct Layer2 : public Next 
{ 
 struct A : public Next::A 
 { 
   void f() 
   { 
     std::cout << "Layer2::A::f() [enter]" << std::endl; 
     Next::A::f(); 
     std::cout << "Layer2::A::f() [leave]" << std::endl; 
   } 
   void g() 
   { 
     std::cout << "Layer2::A::g() [enter]" << std::endl; 
     Next::A::g(); 
     std::cout << "Layer2::A::g() [leave]" << std::endl; 
   } 
 }; 
};

Considering Layer2<Layer1<...>>, the problem here is that any call of
f() and g() from a layer above Layer2 will properly cascade down to
the Layer2::A::g(), and thus display the proper logging messages. But
any call of f() and g() from below Layer2 will not log anything since
the call would have been statically binded to the g() available at the
time the call was made.
This means that calling f() from any layer above Layer2 will obviously
still always call Layer1::A::g() from Layer1::A::f() and not display
the logging messages.
I came up with 2 solutions to this problem:

  1. Virtuality: clearly not acceptable. The whole point of mixin layers
    is to avoid virtuality when not necessary.

  2. Adding a template parameter to the layers to provide the previous
    layer, something of the kind.

.

template <typename Next, template <typename> class Prev> 
struct Layer2 : public Next 
{ 
 typedef Next next_t; 
 struct A : public Next::A 
 { 
   void f() 
   { 
     std::cout << "Layer2::A::f() [enter]" << std::endl; 
     Next::A::f(); 
     std::cout << "Layer2::A::f() [leave]" << std::endl; 
   } 
   void g() 
   { 
     std::cout << "Layer2::A::g() [enter]" << std::endl; 
     Next::A::g(); 
     std::cout << "Layer2::A::g() [leave]" << std::endl; 
   } 
 }; 
}; 

template <typename Next, template <typename> class Prev> 
struct Layer1 : public Next 
{ 
 typedef Next next_t; 
 struct A : public Next::A 
 { 
   void f() 
   { 
     std::cout << "Layer1::A::f() [enter]" << std::endl; 
     ((typename Prev<Layer1<Next,Prev> >::A*)this)->g(); 
     std::cout << "Layer1::A::f() [leave]" << std::endl; 
   } 
   void g() 
   { 
     std::cout << "Layer1::A::g() [enter]" << std::endl; 
     std::cout << "Layer1::A::g() [leave]" << std::endl; 
   } 
 }; 
}; 

typedef Layer2<Layer1<Layer0,Layer2>,NullType> Application;

Well, it works, but I would like to hide this second template
parameter since it is redundant.
I wondered if any of you ever encountered such problem, and what
solutions did you developped to solve it, since there is a clear lack
of articles on mixin layers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文