我有一个可以解析字符串(日期)的类。我希望能够解析普通字符串和宽字符串:
MyClass x;
x.parse("2018-02-27");
x.parse(L"2018-02-27");
由于解析普通字符串和宽字符串的代码基本相同,因此使用模板是有意义的:
template<typename CharT>
void parse(const CharT *str)
{
// ...
}
现在,为了解析我将使用get_time函数。它需要fmt
参数,类型为const CharT *
,并且我想为其提供字符串文字。它必须是普通或宽字符串文字,具体取决于模板类型参数:
template<typename CharT>
void parse(const CharT *str)
{
tm date;
basic_istringstream<CharT> date_stream{str};
date_stream >> get_time(&date, ("%Y-%m-%d" or L"%Y-%m-%d", but how to choose??) );
// ...
}
我只对两个模板实例化感兴趣:char和wchar_t。我试图使用非类型模板参数,但没有设法获得任何编译。
实现函数/模板最优雅的方法是什么?
答案 0 :(得分:3)
添加特质类:
template <typename CharT>
struct format {
static const CharT* const v;
};
template<> const char* const format<char>::v="%Y-%m-%d";
template<> const wchar_t* const format<wchar_t>::v=L"%Y-%m-%d";
然后用作:
date_stream >> get_time(&date, format<CharT>::v);
如果你有野心,你可以将实际的重复格式合并到#define
(然后在必要时使用标记粘贴在前面粘贴L
- 但实际上,我认为& #39;更多的机械而不是它的价值。
答案 1 :(得分:2)
我第一次尝试鞋拔if constexpr
并没有顺利进行,但变量模板看起来不错:
template <typename CharT>
constexpr CharT const *timeFmt;
template <>
constexpr auto timeFmt<char> = "%Y-%m-%d";
template <>
constexpr auto timeFmt<wchar_t> = L"%Y-%m-%d";
template <typename CharT>
void parse(const CharT *str)
{
std::tm date;
std::basic_istringstream<CharT> date_stream{str};
date_stream >> std::get_time(&date, timeFmt<CharT>);
// ...
}
为了记录,这是我第一次尝试时出现的丑陋的事情:
template<typename CharT>
void parse(const CharT *str)
{
std::tm date;
std::basic_istringstream<CharT> date_stream{str};
date_stream >> std::get_time(&date, []{
if constexpr (std::is_same_v<CharT, wchar_t>)
return L"%Y-%m-%d";
else
return "%Y-%m-%d";
}());
// ...
}
答案 2 :(得分:0)
除变量模板和类模板外,还可以使用功能模板:
template<typename T> const T* get_format_str();
然后,char
和wchar_t
的相应专精:
template<> const char* get_format_str<char>() { return "%Y-%m-%d"; }
template<> const wchar_t* get_format_str<wchar_t>() { return L"%Y-%m-%d"; }
在parse()
功能模板中使用此功能模板:
date_stream >> get_time(&date, get_format_str<TChar>());
这种方法的优点是: