字符串参数与格式化的模板参数

时间:2015-01-25 12:13:50

标签: c++ templates design-patterns

我想知道提供格式字符串的这两种方法中的一种是否可以被认为是“更正确”。显然两者都有效,但是需要在命名空间中维护一系列常量字符串,而另一个使用类:

#include <ctime>
#include <iostream>

// Method 1: constant strings:
char const* STANDARD = "%c";
char const* ISO8601  = "%Y-%m-%dT%H:%M:%S%z";

const std::string timestamp(char const* format) {
  time_t raw_time;
  time(&raw_time);
  struct tm* time_info = localtime(&raw_time);
  const size_t maxsize = 80;
  char time_str[maxsize];
  strftime(time_str, maxsize, format, time_info);
  return time_str;
}

// Method 2: Class-based formatter used as a template parameter:
struct standard {
  static inline char const* format() { return "%c"; }
};

struct iso8601 {
  static inline char const* format() { return "%Y-%m-%dT%H:%M:%S%z"; }
};

// The formatter is supplied as a template parameter.
template<typename T>
const std::string timestamp() {
  time_t raw_time;
  time(&raw_time);
  struct tm* time_info = localtime(&raw_time);
  const size_t maxsize = 80;
  char time_str[maxsize];
  strftime(time_str, maxsize, T::format(), time_info);
  return time_str;
}

int main() {
  // Method 1: constant strings:
  std::cout << timestamp(ISO8601) << std::endl;

  // Method 2: template:
  std::cout << timestamp<iso8601>() << std::endl;
}

思考?建议?我对模板编程(特征,策略等)并不熟悉,所以我真的很好奇其中一个比另一个“更好”或“更正确”。

1 个答案:

答案 0 :(得分:1)

如果你要命名不同的格式,并且想要一个常量名称 所有的呼叫站点,然后明显的解决方案是这样的:

extern char standard[] = "%c";
extern char iso8601[] = "%Y-%m-%dT%H:%M:%S%z";

//  ...

template <char const* format>
std::string timestamp()
{
    //  ...
}

如果命名格式太多,您甚至可以使用显式格式 专业化:

template <char const* format> std::string timestamp();
template<> std::string timestamp<standard>()
{
    //  ...
}
template <> std::string timestamp<iso8601>()
{
    //  ...
}

如果您要动态评估格式,我不知道在哪里 这些给你带来了很多std::string timestamp( char const* format )。 关于使用模板的唯一优势是解决方案 显式实例化确保您永远不会得到任何东西 已知格式;如果你的话,代码将无法编译和链接 没有明确的实例化。这反过来意味着你没有 需要任何额外的检查,你的缓冲区足够大(你 无论如何都省略 - 在你的两个实现中,它都可以用于a 用户给出一个会导致缓冲区溢出的人为字符串。