【问题标题】:Generate a unique type or id for each template instantiation? ( example observer pattern )为每个模板实例化生成唯一的类型或 id? (示例观察者模式)
【发布时间】:2013-08-12 20:46:20
【问题描述】:

有没有一种方法或技术可以在编译时为每个模板实例化生成唯一类型或 ID?

例如这个观察者模式:

#include <set>
#include <iostream>

template <typename T>
struct type2type {};    // maybe int2type


template<class T, class T_UNIQUE>
struct OBSERVER_BASE
{
  virtual void notify ( T, type2type< T_UNIQUE > ) = 0;
};

template<class T, class T_UNIQUE>
struct SUBJECT_BASE
{
  // This i like to do without the T_UNIQUE parameter
  typedef T_UNIQUE unique_type;

  std::set< OBSERVER_BASE< T, unique_type >* > my_observer{};

  void do_notify ()
  {
    for ( auto obs : my_observer )
      obs->notify ( T{}, type2type< unique_type >{} );
  }
};


class X {};
class Y {};
                                          // manual unique required?
class Subject_A : public SUBJECT_BASE< X, Subject_A > {};
class Subject_B : public SUBJECT_BASE< X, Subject_B > {};
class Subject_C : public SUBJECT_BASE< Y, Subject_C > {};

// typedef UNIQUE_. only to illustrate the idea 
typedef typename Subject_A::unique_type UNIQUE_A;
typedef typename Subject_B::unique_type UNIQUE_B;
typedef typename Subject_C::unique_type UNIQUE_C;

class Observer :
  public OBSERVER_BASE< X, UNIQUE_A >,
  public OBSERVER_BASE< X, UNIQUE_B >,
  public OBSERVER_BASE< Y, UNIQUE_C >
{
  virtual void notify ( X, type2type< UNIQUE_A > ) override
  {
    std::cout << "x from Subject_A" << std::endl;
  }

  virtual void notify ( X, type2type< UNIQUE_B > ) override
  {
    std::cout << "x from Subject_B" << std::endl;
  }

  virtual void notify ( Y, type2type< UNIQUE_C > ) override
  {
    std::cout << "y from Subject_C" << std::endl;
  }
};

int main ( int argc, char **argv )
{
  Subject_A sub_a {};
  Subject_B sub_b {};
  Subject_C sub_c {};

  Observer obs {};

  sub_a.my_observer.insert( &obs );
  sub_b.my_observer.insert( &obs );
  sub_c.my_observer.insert( &obs );

  sub_a.do_notify();
  sub_b.do_notify();
  sub_c.do_notify();
}

有没有办法以这种方式做到这一点(无需手动唯一参数)? 我知道听起来很奇怪...

template<class T>
struct SUBJECT_BASE
{
  typedef AUTOMATIC_UNIQUE_TYPE__OR__WHAT_EVER unique_type;
};

class Subject_A : public SUBJECT_BASE< X > {};
class Subject_B : public SUBJECT_BASE< X > {};
class Subject_C : public SUBJECT_BASE< Y > {};

【问题讨论】:

  • 你可以使用typeid(T),或std::type_index吗?
  • @KerrekSB:似乎目标是Subject_ASubject_B 具有唯一的基类,尽管它们都使用SUBJECT_BASE&lt;X&gt;
  • SUBJECT_BASE&lt;T&gt; 是唯一类型。
  • @Cory Nelson: 但我想使用T_UNIQUE 来重载通知方法notify ( T, type2type&lt; T_UNIQUE &gt; ) UNIQUE = SUBJECT_BASE<T> 不起作用,因为T 可以是同一类型的两倍或更多倍.

标签: c++ templates unique


【解决方案1】:

我认为没有办法实现您的要求,但有可能实现您想要的。这个实现不需要手动UNIQUE_TYPE

template<class T>
class Subject
{
  std::vector<std::function<void(T)>> observers;

public:
  void do_notify () {
    for ( auto& obs : observers )
      obs( T{} );
  }

  void add_listener(std::function<void(T)> l) {
      observers.emplace_back(std::move(l));
  }
};

class X {};
class Y {};

int main ()
{
  Subject<X> sub_a {};
  Subject<X> sub_b {};
  Subject<Y> sub_c {};

  sub_a.add_listener([](X){std::cout << "x from Subject_A" << std::endl;});
  sub_b.add_listener([](X){std::cout << "x from Subject_B" << std::endl;});
  sub_c.add_listener([](Y){std::cout << "y from Subject_C" << std::endl;});

  sub_a.do_notify();
  sub_b.do_notify();
  sub_c.do_notify();
}

但它的 OOP-ey 比您发布的代码要少得多。 (Live at Coliru)

【讨论】:

  • 这是观察者模式的一个很好的解决方案。而且我们不需要观察者基类,也不需要虚拟方法。 (Code @ Coliru 基于 Casey -> 带有观察者类的版本)
  • 大肠杆菌链接已过期;太糟糕了,我很想看到它。
猜你喜欢
  • 2011-05-22
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
  • 2011-01-14
  • 2016-07-29
  • 2012-12-01
相关资源
最近更新 更多