C++ 有类似 scala 的 mixin 吗?

发布于 2024-07-12 19:53:14 字数 81 浏览 9 评论 0原文

Scala 混合

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

分開簡單 2024-07-19 19:53:14

Scala mixin 的某些方面可以使用多重(虚拟)继承来满足。 不幸的是,这往往带来的问题多于它解决的问题。 另外,你不能即时混合和匹配超类a la

val me = new Human with Coder with Musician

如果你真的,真的想要真正的混合,你几乎必须使用类似模板解决方案的东西@Logan Capaldo 在答案中提出。

Some aspects of Scala mixins can be satisfied using multiple (virtual) inheritance. Unfortunately, this often introduces more problems than it solves. Also, you can't mix and match superclasses on the fly a la:

val me = new Human with Coder with Musician

If you really, really want true mixins, you almost have to go with something like the template solution proposed in the answer by @Logan Capaldo.

尴尬癌患者 2024-07-19 19:53:14

为了重申和扩展之前电子邮件中提到的内容,我首先给您一个如何在 C++ 中实现 Scala Ordered 特征的示例,然后让我展示如何在实例化时混合任意数量的“特征”。

让我们首先从 Ordered 特征开始。 如果您熟悉 Scala SDK,您会注意到有一个 Ordered 特征。 这用于通过实现简单的“比较”方法来提供总排序。 在 C++ 中,您可以执行以下操作:

template <typename T>
class Ordered {
public:
    virtual int32_t compare(const T& that) = 0;
    bool operator >(const T& that) {return this->compare(that) == 1; }
    bool operator >=(const T& that) {return this->compare(that) >= 0; }

    bool operator ==(const T& that) { return this->compare(that) == 0; }

    bool operator <=(const T& that) {return this->compare(that) <= 0; }
    bool operator <(const T& that) {return this->compare(that) == -1; }
};

然后,要为 C++ 类提供排序属性,您可以执行以下操作:

class MyOrderedType : public Ordered<MyOrderedType> {
public:
  // Your ctor/dtors, methods
public:
  int compare(const MyOrderedType& that);
};

显然,您可以根据需要混合任意数量的“特征”,但如果您这样做,则可以' t 在实例化时添加或删除特征。 有一个简单的解决方案吗? 有点儿。

听说过 C++0x 可变参数模板吗? 这提供了一种在模板实例化时混合所需数量的特征的方法。

技巧很简单,只需按如下方式声明您的主机类:

template <typename... MIXINS>
class Host : public MIXINS... {
 // Your implementation
};

这里有什么问题? 好吧,问题是不可能做这样的事情:

template <typename... MIXINS>
class Host : public MIXINS<HOST>... {
    // Your implementation
};

在某些情况下这会很方便。

无论如何,C++ 都有一些基本机制可以让您模拟 Scala Mix-ins 的某些方面。 然而,它不能做的是堆叠行为。

HTH。

Just to reiterate and extend what mentioned in previous emails let me first give you an example of how to implement the Scala Ordered trait in C++ and then let me show how you can mix-in an arbitrary number of "traits" at instantiation time.

Let's start first with the Ordered trait. If you are familiar with the Scala SDK you'll have noticed that there is an Ordered trait. This is used to provide total ordering by means of implementing a simple "compare" method. In C++, you could do the same as follows:

template <typename T>
class Ordered {
public:
    virtual int32_t compare(const T& that) = 0;
    bool operator >(const T& that) {return this->compare(that) == 1; }
    bool operator >=(const T& that) {return this->compare(that) >= 0; }

    bool operator ==(const T& that) { return this->compare(that) == 0; }

    bool operator <=(const T& that) {return this->compare(that) <= 0; }
    bool operator <(const T& that) {return this->compare(that) == -1; }
};

Then, to give ordering property to a C++ class you can do the following:

class MyOrderedType : public Ordered<MyOrderedType> {
public:
  // Your ctor/dtors, methods
public:
  int compare(const MyOrderedType& that);
};

Obviously you can mix-in as many "traits" as you want but if you do this way you can't add or remove traits at instantiation time. Is there a simple solution for this? Kind-of.

Have heard about the C++0x variadic templates? This provides a way of mixing-in as many traits as you want at template instantiation time.

The trick is simple, just declare your host class as follows:

template <typename... MIXINS>
class Host : public MIXINS... {
 // Your implementation
};

What is the catch here? Well, the issue is that it is not possible to do something like this:

template <typename... MIXINS>
class Host : public MIXINS<HOST>... {
    // Your implementation
};

Which in some cases would have been handy.

In any case, C++ has some basic mechanism that allow you to emulate some aspects of Scala's Mix-ins. What it can't do, however, is stacking behavior.

HTH.

£烟消云散 2024-07-19 19:53:14

不,但它可以用模板进行不同程度的伪造:

template<typename AbsIterator> 
class RichIterator : public AbsIterator {
public:
   template<typename FuncType>
   void foreach(FuncType f) { while( hasNext() ) f( next() ); }
};

class StringIterator {
  std::string m_s;
  int i;
public:
  typedef char T;
  StringIterator() : m_s(), i(0) {} // Unfortunately need this, or 
                                    // else RichIterator
                                    // gets way more complicated
  StringIterator(const std::string &s) : m_s(s), i(0) {}
  void swap(StringIterator& other) {
     m_s.swap(other.m_s);
     std::swap(i, other.i);
  }
  void reset_str(const std::string& s) {
     StringIterator(s).swap(*this);
  }
  bool hasNext() { return i < m_s.length(); }
  char next() { return m_s[i++]; }
};

template<typename Outputable>
void println(const Outputable& o) {
   std::cout << o << std::endl;
}

int main(int argc, char **argv) {
  typedef RichIterator<StringIterator> Iter;
  Iter iter;
  iter.reset_str(argv[1]);
  iter.foreach(&println<Iter::T>);
}

说实话,我还没有通过编译来测试它,但你应该明白这个想法。

No, but it can be faked to varying degrees with templates:

template<typename AbsIterator> 
class RichIterator : public AbsIterator {
public:
   template<typename FuncType>
   void foreach(FuncType f) { while( hasNext() ) f( next() ); }
};

class StringIterator {
  std::string m_s;
  int i;
public:
  typedef char T;
  StringIterator() : m_s(), i(0) {} // Unfortunately need this, or 
                                    // else RichIterator
                                    // gets way more complicated
  StringIterator(const std::string &s) : m_s(s), i(0) {}
  void swap(StringIterator& other) {
     m_s.swap(other.m_s);
     std::swap(i, other.i);
  }
  void reset_str(const std::string& s) {
     StringIterator(s).swap(*this);
  }
  bool hasNext() { return i < m_s.length(); }
  char next() { return m_s[i++]; }
};

template<typename Outputable>
void println(const Outputable& o) {
   std::cout << o << std::endl;
}

int main(int argc, char **argv) {
  typedef RichIterator<StringIterator> Iter;
  Iter iter;
  iter.reset_str(argv[1]);
  iter.foreach(&println<Iter::T>);
}

To be totally honest, I've haven't tested this by compiling it, but you should get the idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文