我想知道提供格式字符串的这两种方法中的一种是否可以被认为是“更正确”。显然两者都有效,但是需要在命名空间中维护一系列常量字符串,而另一个使用类:
#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;
}
思考?建议?我对模板编程(特征,策略等)并不熟悉,所以我真的很好奇其中一个比另一个“更好”或“更正确”。
答案 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
用户给出一个会导致缓冲区溢出的人为字符串。