![](/img/trans.png)
[英]c++11 user defined literals, conflicts with compilation/execution dichotomy
[英]How to get smallest variable with C++11 user defined literals
我一直在研究C ++ 11的一些新功能,并且对其中的一些非常印象深刻,特别是用户定义的文字。
这些允许您定义999_something
形式的文字,其中something
控制对999
以生成文字。 所以不必再使用:
#define MEG * 1024 * 1024
int ten_meg = 10 M;
我认为这样很好地实现大量的下划线,比如1_000_000_blah
,这与Perl的可读性相匹配,虽然Perl在某种程度上可读的想法对我来说似乎很幽默:-)
它对于像1101_1110_b
和0011_0011_1100_1111_b
这样的二进制值也很方便。
显然由于_
字符,这些将需要是原始模式类型,处理C字符串,我没关系。
我无法弄清楚的是如何根据操作数大小提供不同的类型。 例如:
1101_1110_b
应该给一个char
(假设char
当然是8位),而:
0011_0011_1100_1111_b
将提供16位类型。
我可以从文字运算符函数operator""
本身(通过计数数字字符)获取操作数的长度,但返回类型似乎是固定到函数,所以我不能基于此返回不同的类型。
可以在用户定义的类型框架中使用单个后缀_b
来完成,或者我是否需要手动拆分类型( _b8
, _b16
等)并提供大多数重复的功能?
你需要知道你的字符串的大小,唯一的方法是让参数包使用sizeof...
on。 您应该能够通过可变参数模板operator""
实现您想要的功能:
#include <cstdint>
#include <type_traits>
template<char... String>
auto operator "" _b()
-> typename std::conditional<sizeof...(String) <= 8,
uint8_t,
typename std::conditional<sizeof...(String) <= 16,
uint16_t,
uint32_t
>::type
>::type
{
// Do whatever you want here
}
这是一个测试用例:
int main()
{
auto a = 10000001_b;
auto b = 100000001_b;
std::cout << std::boolalpha;
std::cout << std::is_same<decltype(a), uint8_t>::value << "\n"; // true
std::cout << std::is_same<decltype(b), uint16_t>::value << "\n"; // true
}
不幸的是,该解决方案无法处理数字分隔符。 而且, std::conditional
机器非常难看。 你可以用boost::mpl::vector
, boost::mpl::at
和一些算术运算来更好地工作。
感谢Morwenn的回答,我为那些坚持使用C ++ 11的人提出了一个完整的用户自定义二进制文字解决方案:
#include <cstdint>
#include <type_traits>
/// User-defined binary literal for C++11
/// @see https://stackoverflow.com/a/538101 / https://gist.github.com/lichray/4153963
/// @see https://stackoverflow.com/a/17229703
namespace detail {
template<class tValueType, char... digits>
struct binary_literal;
template<char... digits>
struct unsigned_binary_literal
{
using Type = typename std::conditional<sizeof...(digits) <= 8, uint8_t,
typename std::conditional<sizeof...(digits) <= 16, uint16_t,
typename std::conditional<sizeof...(digits) <= 32, uint32_t, uint64_t>::type
>::type
>::type;
};
template<char... digits>
struct signed_binary_literal
{
using Type = typename std::conditional<sizeof...(digits) <= 8, int8_t,
typename std::conditional<sizeof...(digits) <= 16, int16_t,
typename std::conditional<sizeof...(digits) <= 32, int32_t, int64_t>::type
>::type
>::type;
};
template<class tValueType, char high, char... digits>
struct binary_literal<tValueType, high, digits...>
{
static constexpr tValueType value = (static_cast<tValueType>(high == '1') << (sizeof...(digits))) ^ binary_literal<tValueType, digits...>::value;
};
template<class tValueType, char high>
struct binary_literal<tValueType, high>
{
static constexpr tValueType value = (high == '1');
};
} // namespace detail
/// C++11 support for binary literal
/// @tparam digits to transform to an unsigned integer
template<char... digits>
constexpr auto operator "" _bin() -> typename detail::unsigned_binary_literal<digits...>::Type
{
return detail::binary_literal<typename detail::unsigned_binary_literal<digits...>::Type, digits...>::value;
}
/// C++11 support for binary literal
/// @tparam digits to transform to a signed integer
template<char... digits>
constexpr auto operator "" _sbin() -> typename detail::signed_binary_literal<digits...>::Type
{
return static_cast<typename detail::signed_binary_literal<digits...>::Type>(detail::binary_literal<typename detail::unsigned_binary_literal<digits...>::Type, digits...>::value);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.