簡體   English   中英

部分方法專門化

[英]Partial Method Specialization

我有一個 C++ class,在 Logger.hpp 中有一個模板方法,我想向它添加特化以支持其他類,例如 Player.hpp 中的特化。 我想我要實現的是所謂的“部分方法專業化”,如果我錯了請糾正我。

我嘗試了以下(簡化的)代碼:

記錄器.hpp

class Logger {
  public:
  template<typename T, typename... ArgTypes> void log(T message, ArgTypes... args) {
    std::cout << message << std::endl;
    // do more with args...
  }
};

播放器.hpp

#include "Logger.hpp"

class Player {
  public:
  Player(const std::string &name) : name(name) {}
  std::string getName() const { return name; }

  private:
  std::string name;
};

// add support for logger->log(myPlayer, 19, 11)
// (19 and 11 are arbitrary arguments and can be of any number and types)

// unfortunately this line does not compile
// (declaration is incompatible with function template "void Logger::log(T message, ArgTypes ...args)")
template<typename... ArgTypes> void Logger::log<Player>(Player message, ArgTypes... args) {
  std::cout << "Player(name=" << message.getName() << ")" << std::endl;
  // do more with args...
}

我應該如何將功能添加到我的記錄器 class 以允許我記錄我的播放器 class(以及以后的其他類)?

我不想在 Logger.hpp 中添加專業化。 應該可以像處理庫一樣處理 Logger.hpp,任何人都可以自由地在他們的代碼中添加對他們的類型的支持。

另請注意,我在鍵入的第一個參數之后傳遞了一個可變參數(typename ... ArgTypes)。

另請注意,在 C++ output class 上重載 << 運算符也不是一個選項,因為 cout 行稍后將被不同的代碼替換。

我找到了一些適用於我的特定情況的解決方法,它也可能是其他人遇到此類問題的解決方案。

我選擇了特定類型 std::string,而不是第一個日志參數 T 作為模板參數。 至於其他類,我只需添加一個 std::string 轉換運算符,它將生成我想要的任何字符串。

這對我來說很好,因為我最終要處理字符串,我想每次都對 args 做同樣的事情。 新代碼如下所示:

記錄器.hpp

class Logger {
  public:
  template<typename... ArgTypes> void log(std::string message, ArgTypes... args) {
    std::cout << message << std::endl;
    // do more with args...
  }
};

播放器.hpp

#include "Logger.hpp"

class Player {
  public:
  Player(const std::string &name) : name(name) {}
  std::string getName() const { return name; }
  operator std::string() const {
    return std::string("Player(name=") + name + ")";
  }

  private:
  std::string name;
};

如果我不想使用字符串轉換,或者如果我想將一些參數傳遞給我的 function,另一種解決方案是使用 base 和 sub class。這樣的方法可能有效(未測試):

記錄器.hpp

class Loggable {
  public:
  virtual void logMe() = 0;
};

class Logger {
  public:
  template<typename T, typename... ArgTypes> void log(T message, ArgTypes... args) {
    std::cout << message << std::endl;
    // do more with args...
  }

  template<typename... ArgTypes> void log(Loggable *loggable, ArgTypes... args) {
    loggable->logMe();
  }
};

播放器.hpp

#include "Logger.hpp"

class Player : public Loggable {
  public:
  Player(const std::string &name) : name(name) {}
  std::string getName() const { return name; }
  void logMe() override {
    std::cout << "Player(name=" << message.getName() << ")" << std::endl;
  }

  private:
  std::string name;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM