我可以从 signed char* 或 unsigned char* 中获取 char* 吗?
Can I get a char* out of either signed char* or unsigned char*?
我必须处理 char
可能未签名的数组(因为它们来自 SCSI 数据块)。我想用这个函数来处理它们:
template <typename CharT, size_t Len>
std::string strFromArray(CharT (&src) [Len])
{
return std::string((typename boost::make_signed<CharT>::type *) src, Len);
}
错误在 std::string
构造函数调用中,它不能取 signed char
/unsigned char
但只会取 char
.
我当然可以用 (char *) src
替换强制转换,但是如果我传入非字符类型,我将丢失所有编译器错误。
我该如何编写才能从所有 "charry" 类型中构造字符串?
假设到 string
的转换表示字节数组携带以 null 结尾的 C 字符串(例如字符串文字):
#include <string>
#include <stddef.h>
namespace my {
using std::string;
using Size = ptrdiff_t;
namespace detail {
auto is_char_type( char const* ) -> bool;
auto is_char_type( signed char const* ) -> bool;
auto is_char_type( unsigned char const* ) -> bool;
} // namespace detail
template< class Char, Size n >
auto string_from( Char (&src) [n] )
-> string
{
(void) sizeof( detail::is_char_type( src ) );
return string( src, src + n - 1 );
}
} // namespace my
auto main() -> int
{
unsigned char const data[] = "Blah";
auto const s = my::string_from( data );
#ifdef TEST_WCHAR
wchar_t const wdata[] = L"Blah";
auto const ungood_s = my::string_from( wdata ); // Doesn't compile.
#endif
}
如果不是字符串而是关于任意二进制数据,那么只使用 src + n
而不是 src + n - 1
。
但是,对于二进制数据,您可能需要一个单独的长度,即不使用原始数组本身的长度。
我会尽可能简单,并使用:
#include <iostream>
#include <string>
namespace conv {
template <size_t len>
std::string strFromArray(const char(&arr)[len])
{
static_assert(len > 0, "don't use zero-sized arrays");
return std::string(arr, len - 1);
}
template <size_t len>
std::string strFromArray(const unsigned char(&arr)[len])
{
static_assert(len > 0, "don't use zero-sized arrays");
return std::string((const char *)arr, len - 1);
}
}
int main()
{
const char charstr[] = "abcd";
std::string str = conv::strFromArray(charstr);
std::cout << str << std::endl;
const unsigned char ucharstr[] = "efg";
str = conv::strFromArray(ucharstr);
std::cout << str << std::endl;
/*not possible:
const wchar_t wcharstr[] = L"hijk";
str = conv::strFromArray(wcharstr);
*/
}
只需在您的函数中放置一个静态断言并稍作修改即可:
#include <string>
template <typename CharT, std::size_t Len>
std::string strFromArray(CharT (&src) [Len])
{
// Anythig which looks like a char is considered a char.
static_assert(sizeof(CharT) == sizeof(char), "Invalid Character Type");
std::size_t n = Len;
// Do not use a terminating zero (might be wrong if the source is no char
// literal, but an array of binary data.
if( ! src[n-1])
--n;
return std::string(src, src + n);
}
int main()
{
char c[3] = {};
signed char sc[3] = {};
unsigned char uc[3] = {};
wchar_t wc[3] = {};
strFromArray(c);
strFromArray(sc);
strFromArray(uc);
// error: static assertion failed: Invalid Character Type
// strFromArray(wc);
}
我必须处理 char
可能未签名的数组(因为它们来自 SCSI 数据块)。我想用这个函数来处理它们:
template <typename CharT, size_t Len>
std::string strFromArray(CharT (&src) [Len])
{
return std::string((typename boost::make_signed<CharT>::type *) src, Len);
}
错误在 std::string
构造函数调用中,它不能取 signed char
/unsigned char
但只会取 char
.
我当然可以用 (char *) src
替换强制转换,但是如果我传入非字符类型,我将丢失所有编译器错误。
我该如何编写才能从所有 "charry" 类型中构造字符串?
假设到 string
的转换表示字节数组携带以 null 结尾的 C 字符串(例如字符串文字):
#include <string>
#include <stddef.h>
namespace my {
using std::string;
using Size = ptrdiff_t;
namespace detail {
auto is_char_type( char const* ) -> bool;
auto is_char_type( signed char const* ) -> bool;
auto is_char_type( unsigned char const* ) -> bool;
} // namespace detail
template< class Char, Size n >
auto string_from( Char (&src) [n] )
-> string
{
(void) sizeof( detail::is_char_type( src ) );
return string( src, src + n - 1 );
}
} // namespace my
auto main() -> int
{
unsigned char const data[] = "Blah";
auto const s = my::string_from( data );
#ifdef TEST_WCHAR
wchar_t const wdata[] = L"Blah";
auto const ungood_s = my::string_from( wdata ); // Doesn't compile.
#endif
}
如果不是字符串而是关于任意二进制数据,那么只使用 src + n
而不是 src + n - 1
。
但是,对于二进制数据,您可能需要一个单独的长度,即不使用原始数组本身的长度。
我会尽可能简单,并使用:
#include <iostream>
#include <string>
namespace conv {
template <size_t len>
std::string strFromArray(const char(&arr)[len])
{
static_assert(len > 0, "don't use zero-sized arrays");
return std::string(arr, len - 1);
}
template <size_t len>
std::string strFromArray(const unsigned char(&arr)[len])
{
static_assert(len > 0, "don't use zero-sized arrays");
return std::string((const char *)arr, len - 1);
}
}
int main()
{
const char charstr[] = "abcd";
std::string str = conv::strFromArray(charstr);
std::cout << str << std::endl;
const unsigned char ucharstr[] = "efg";
str = conv::strFromArray(ucharstr);
std::cout << str << std::endl;
/*not possible:
const wchar_t wcharstr[] = L"hijk";
str = conv::strFromArray(wcharstr);
*/
}
只需在您的函数中放置一个静态断言并稍作修改即可:
#include <string>
template <typename CharT, std::size_t Len>
std::string strFromArray(CharT (&src) [Len])
{
// Anythig which looks like a char is considered a char.
static_assert(sizeof(CharT) == sizeof(char), "Invalid Character Type");
std::size_t n = Len;
// Do not use a terminating zero (might be wrong if the source is no char
// literal, but an array of binary data.
if( ! src[n-1])
--n;
return std::string(src, src + n);
}
int main()
{
char c[3] = {};
signed char sc[3] = {};
unsigned char uc[3] = {};
wchar_t wc[3] = {};
strFromArray(c);
strFromArray(sc);
strFromArray(uc);
// error: static assertion failed: Invalid Character Type
// strFromArray(wc);
}