c++ - 重构为模板

标签 c++ templates crtp

我想写一些字符串包装器,如果它对它们的类​​型有效,它将接受一个字符串:

  • 长度 有效字符串:mm、m、ft、in
  • Angle 有效字符串:deg, rad

我想象这样的用途:

Length len = read_from_keyboard(); // or some means of initialization
if( len.is_valid() )   { ...   }

所以我写了这些实现。

struct Length
{
  QString m;

  Length() {}

  Length( QString s )   {   if( is_valid_string(s) )  {  m = s; }      }

  QString operator() () {   return m;      }

  bool is_valid()       {   return is_valid_string(m);      }

  static bool is_valid_string( QString s ) { 
    return s == "mm" || s=="m" || s=="ft" || s=="in";
  }
};

struct Angle{
  QString m;

  Angle() {}

  Angle( QString s )    {   if( is_valid_string(s) )  {  m = s; }      }

  QString operator() () {   return m;      }

  bool is_valid()       {   return is_valid_string(m);      }

  static bool is_valid_string( QString s ) { 
    return s == "deg" || s=="rad";
  }
};

这在我看来是某种形式的静态多态性,is_valid_string() 是它们在实现上的唯一区别。

因为我有很多这样的类,所以我想到使用静态继承(而不是通过虚拟继承)来掌握通用功能。

所以,我想到了使用奇怪的重复模板模式:

template <class T>
struct ConstrainedText {
  QString m;

  ConstrainedText() {}

  ConstrainedText( QString s ) {   if( T::is_valid_string(s) )   {  m = s;  }    }

  QString operator() ()        {   return m;      }

  bool is_valid()              {   return T::is_valid_string(m);    }

};


struct Angle : public ConstrainedText<Angle> {
   static bool is_valid_string( QString s ) { 
      return s == "deg" || s="rad";
   }  
};


struct Length : public ConstrainedText<Angle> {
   static bool is_valid_string( QString s ) { 
      return s == "mm" || s="m" || s=="ft" || s=="in";
   }  
};

但现在我丢失了基类中的隐式构造函数,我必须重写它们!

为了拥有相同的接口(interface) [default constructor, implicit constructor and is_value() 有没有其他方法可以实现它] 并且只为不同的部分编写最少的代码(静态 is_valid_string() )?

我知道我可以使用预处理器,但我希望代码对调试器友好。

最佳答案

正如其他人所指出的,由于构造函数不是继承的,因此您将不得不重新定义它们。但是你可以做这样的事情,code at ideone.com :

#include <string>
#include <stdexcept>
#include <iostream>

template <class T>        
class ConstrainedText {        
  std::string m;                 

protected:
  ConstrainedText() {}
  ~ConstrainedText() {}
public: 
  bool is_valid() {        
    return T::is_valid_string(m);        
  }        

  static T Create(std::string const & s)
  {
      if (T::is_valid_string(s)) {
          T t;
          static_cast<ConstrainedText<T>&>(t).m = s;
          return t;
      }

      throw std::runtime_error("invalid input!");
  }
};        

struct Angle : public ConstrainedText<Angle> {        
   static bool is_valid_string( std::string s ) {         
      return s == "deg" || s=="rad";        
   }          
};        


struct Length : public ConstrainedText<Length> {        
   static bool is_valid_string( std::string s ) {         
      return s == "mm" || s == "m" || s == "ft" || s == "in";        
   }          
};        

int main()
{
   auto a = Angle::Create("deg");
   auto l = Length::Create("mm");

   try {
       Angle::Create("bimbo");
   } catch (std::runtime_error & pEx) {
       std::cout << "exception as expected" << std::endl;
   }

   try {
       Length::Create("bimbo");
   } catch (std::runtime_error & pEx) {
       std::cout << "exception as expected" << std::endl;
   }
}

关于c++ - 重构为模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12355841/

相关文章:

c++ - 如何初始化一个数组的 systemc 端口名称?

java - 如何为 Android 中的 ListView 的每个项目设置背景图片?

c++ - 如何将 boost::intrusive_ptr 用于类模板中的私有(private)嵌套类

c++ - 看似模棱两可的模板函数重载

将自身转换为派生类后可以访问c++基本私有(private)方法吗?

c++ - std::optional 的 const_cast 等价物

C++友元函数不能访问私有(private)成员

c++ - 缩放后重新定位矩形

每个派生类的 C++ 分离静态字段

c++ - 使用 CRTP 或 PBCP 或 duck-typing boost ASIO