tin*_*lyx 21 c++ templates type-traits c++11
我正在尝试编写一个模板is_c_str来测试一个类型是否是一个c风格的字符串.我需要这个尝试编写一个to_string函数,如我在这里的另一个问题所示:
STL容器迭代器的模板特化?.
我需要分开c_str和其他类型的指针和迭代器,以便我可以在face值处表示第一个,并将指针/迭代器渲染为不透明的"itor"或"ptr".代码如下:
#include <iostream>
template<class T>
struct is_c_str
: std::integral_constant<
bool,
!std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
> {};
int main() {
auto sz = "Hello"; //Or: const char * sz = "Hello";
int i;
double d;
std::cout << is_c_str<decltype(sz)>::value << ", "
<< is_c_str<decltype(i)>::value << ", "
<< is_c_str<decltype(d)>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
然而,is_c_str仅捕获没有const char *,还int和double.以上代码输出:
1, 1, 1
Run Code Online (Sandbox Code Playgroud)
(截至gcc-4.8.1).
我的问题是如何修复is_c_str以正确捕获C风格的字符串?
Pra*_*ian 20
你想检查类型是否与a相同char *,但是你否定了结果std::is_same,这显然不会产生正确的结果.所以让我们删除它.
template<class T>
struct is_c_str
: std::integral_constant<
bool,
std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
> {};
Run Code Online (Sandbox Code Playgroud)
但是,现在这将导致输出0, 0, 0.现在的问题是remove_cv删除顶级cv限定符,但constin char const *不是顶级的.
如果你想匹配两者char *,char const *最简单的解决方案是:
template<class T>
struct is_c_str
: std::integral_constant<
bool,
std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value ||
std::is_same<char const *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
> {};
Run Code Online (Sandbox Code Playgroud)
以上版本仍然不匹配char[].如果你想匹配这些呢,降低组合的详细程度std::remove_reference和std::remove_cv使用std::decay来代替.
template<class T>
struct is_c_str
: std::integral_constant<
bool,
std::is_same<char const *, typename std::decay<T>::type>::value ||
std::is_same<char *, typename std::decay<T>::type>::value
> {};
Run Code Online (Sandbox Code Playgroud)
我试过这个似乎工作:
#include <iostream>
template<class T>
struct is_c_str : std::integral_constant<bool, false> {};
template<>
struct is_c_str<char*> : std::integral_constant<bool, true> {};
template<>
struct is_c_str<const char*> : std::integral_constant<bool, true> {};
int main() {
auto sz = "Hello";
int i;
double d;
std::cout << is_c_str<decltype(sz)>::value << ", "
<< is_c_str<decltype(i)>::value << ", "
<< is_c_str<decltype(d)>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
显然列举每个案例并不像把一般谓词列入其中那么优雅std:integral_constant,但另一方面,谓词对于像我这样的白痴来说是外来语言,而"蛮力"模板专业化在某种程度上更易于理解,并且在这种情况下可行很少有专业.
类型sz是char const*,但std::remove_cv<>只删除顶级const,因此您无法char*完成其应用程序.相反,你可以检查char const*完全分解类型后std::decay<>:
namespace detail
{
template<class T>
struct is_c_str : std::is_same<char const*, T> {};
}
template<class T>
struct is_c_str : detail::is_c_str<typename std::decay<T>::type> {};
int main() {
auto sz = "Hello";
int i;
double d;
std::cout << is_c_str<decltype(sz)>::value << ", "
<< is_c_str<decltype(i)>::value << ", "
<< is_c_str<decltype(d)>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
你也错误地否定了这种情况.我也解决了这个问题.
有几个问题。
线路
!std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
Run Code Online (Sandbox Code Playgroud)
需要是
std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
Run Code Online (Sandbox Code Playgroud)你的使用逻辑typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value有缺陷。它不会转换char const*为char*. 它可以转换char* const为char*.
你需要的是:
template<class T>
struct is_c_str
: std::integral_constant<
bool,
std::is_same<char *, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value ||
std::is_same<char const*, typename std::remove_reference<typename std::remove_cv<T>::type>::type>::value
> {};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2991 次 |
| 最近记录: |