繁体   English   中英

如何使用C ++ 11用户定义的文字获取最小的变量

[英]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_b0011_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::vectorboost::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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM