我正在尝试创建一个程序,该程序可以在编译时从十进制数转换为十六进制数。 不幸的是,我是元编程的新手,在编译时我找不到一种方法。 有什么想法可以解决这个问题吗?

如何在不违反模板元编程原理的情况下表示这样的数字。

===============>>#1 票数:1

#include <algorithm>        // std::reverse
#include <iterator>         // std::begin, std::end
#include <iostream>
#include <tuple>
#include <type_traits>      // std::integral_constant

namespace detail {
    using std::tuple;
    using std::tuple_cat;
    using std::integral_constant;

    template< unsigned x, int n_digits >
    struct Hex_tuple_
    {
        using Type = decltype( tuple_cat(
            typename Hex_tuple_< x & ((1 << 2*n_digits) - 1), n_digits/2 >::Type(),
            typename Hex_tuple_< (x >> 2*n_digits), n_digits/2 >::Type()
            ) );
    };

    template< unsigned x >
    struct Hex_tuple_< x, 1 >
    {
        using Type = tuple< integral_constant< int, x > >;
    };

}  // namespace detail

template< unsigned x >
using Hex_ = typename detail::Hex_tuple_< x, 2*sizeof( x ) >::Type;

template< int... digit >
auto operator<<(
    std::ostream& stream,
    const std::tuple< std::integral_constant< int, digit >... >&
    )
    -> std::ostream&
{
    int digits[] = { digit... };
    std::reverse( std::begin( digits ), std::end( digits ) );
    for( int x : digits )
    {
        stream << "0123456789ABCDEF"[x];
    }
    return stream;
}

auto main() -> int
{
    std::cout << Hex_<123456>() << "\n";
}

===============>>#2 票数:1

构建在编译时表示给定无符号整数的基数B的一般问题非常有趣。 可以通过应用构建编译时std::array的宝贵技术来简洁地解决此问题 ,至少可以回溯到此答案

如下定义的函数模板digits将返回一个以char表示的编译时以空值终止的std::array ,其中char包含表示整数N的基本Base数字,对于在合理范围[2,36]中的Base (数字'0-9A-Z' )

#include <type_traits>
#include <array>

// Get the number of base `base` digits in `n`
constexpr std::size_t base_digits(unsigned long n, unsigned base) 
{
    return (n / base) == 0 ? 1 : 1 + base_digits(n / base,base);
}

// Convert the remainder `r` of division by some base to a based digit
constexpr char based_digit(unsigned r)
{
    return r > 36 ? '!' : r < 10 ? '0' + r : 'A' + r - 10;
}

template <unsigned long N, unsigned Base, 
    std::size_t Len = base_digits(N,Base) + 1, unsigned ...Rems>
constexpr std::array<char, Len> 
digits(std::enable_if_t<(Base > 1 && Base <= 36 && N < Base)> * = nullptr)
{
    return std::array<char,Len>{{based_digit(N), Rems...,0}};
}

template <unsigned long N, unsigned Base, 
    std::size_t Len = base_digits(N,Base) + 1, unsigned ...Rems>
constexpr std::array<char,Len> 
digits(std::enable_if_t<(Base > 1 && Base <= 36 && N >= Base)> * = nullptr)
{
    return digits<N / Base, Base, Len, based_digit(N % Base), Rems...>();  
}

在此测试之前添加:

constexpr auto decimal = digits<9876543210,10>();
constexpr auto hex = digits<9876543210,16>();
constexpr auto octal = digits<123456789,8>();
constexpr auto binary = digits<123456789,2>();
constexpr auto b_36 = digits<36 + 35,36>();

static_assert(decimal.size() == 11,"");

#include <iostream>
#include <cassert>

int main() {
    char * pend;    
    assert(std::strtoul(decimal.data(),&pend,10) == 9876543210); 
    std::cout << decimal.data() << std::endl;
    assert(std::strtoul(hex.data(),&pend,16) == 9876543210);
    std::cout << hex.data() << std::endl;
    assert(std::strtoul(octal.data(),&pend,8) == 123456789);
    std::cout << octal.data() << std::endl;
    assert(std::strtoul(binary.data(),&pend,2) == 123456789);
    std::cout << binary.data() << std::endl;
    assert(std::strtoul(b_36.data(),&pend,36) == 36 + 35);
    std::cout << b_36.data() << std::endl;
    return 0;
}

输出为:

9876543210
24CB016EA
726746425
111010110111100110100010101
1Z

(gcc 4.9.2 / clang 3.5.1,-std = c ++ 14。适用于C ++ 11)

  ask by Daemonstool translate from so

未解决问题?本站智能推荐:

1回复

是否有可能获得将根据ADL调用的函数的十进制类型?

这里有一个帖子,询问我认为对我而言等效的内容(函数的地址而不是类型),但问题已经有5年了; 唯一的答案指出,可能没有一个适当的解决方案-如果没有提出特定的原因-并提供了一个部分解决方案,该解决方案要求一个新函数显式地调用每个有问题的ADL函数,以仅利用lambda语义。 我可以使它更通
2回复

将树的编译时转换为元组

我遇到了以下问题: 给定一棵树,该树由Node<>类型的非终端节点和任意类型(如A , B等)的终端节点表示(请参见下文)。 因为我不想使用运行时多态,所以我喜欢通过constexpr函数将树转换为std::tuple ,例如下面示例中立即调用的lambda表达式。
2回复

在编译时构建和访问类型列表

我试图使用c ++模板元编程实现以下功能。 我希望建立一个类型列表,然后一起收集这些类型,并在列表上进行进一步的编译时处理。 例如: foo.h中: bar.h: main.h: 我可以在上面的插槽中插入任何代码,只要list_of_types :: type解
1回复

在编译时填充std :: set?

是否有可能创建(可能是const ) std::set ,它将在编译时填充元素? 我特别想知道std::set / std::unordered_set ,而不是一组模拟集合行为的模板化函数。
3回复

在编译时解决河内的塔楼

我试图在编译时解决河内塔,但我发现了一个问题: 不幸的是, 上面的元程序只打印了6个而不是7个: 最后一次从1移动到3失踪。 这是为什么? 问题可以解决吗?
4回复

使用模板和/或constexpr在编译时构建函数

该代码是在即时更改名称约定的情况下编写的,如果造成混乱,我们深表歉意。 我将在这里重写问题以使其更清楚。 在编译时已知一些数据,两个整数数组D和E长度均为L D每个元素为零或一。 E每个元素都包含[0,L]中的值。 然后,我得到了一个在运行时已知的向量X ,它的长度也为L
2回复

在编译时迭代地过滤与谓词匹配的参数

上下文 首先,一些上下文:我使用一个名为nothing的空struct来模拟类似于“常规void ”的东西,以便美化一些依赖于将多个函数对象链接在一起的接口。 用法示例: 在上面的例子中,所发生的情况是,我包装传递给函数的对象的所有结果when_all在std::tuple
1回复

在编译时初始化double

我正在通过模板元编程来编写浮点运算的编译时实现。 我的实现具有以下特征: 16位有符号整数指数。 32位无符号整数尾数, 无隐式最高有效位1 (这样做是为了简化调试)。 类型如下: 这些操作运行良好,但是现在我需要一种在编译时提取这些值并获取相应的double
1回复

在编译时增量创建数组

受这篇文章的启发, https://stackoverflow.com/a/6730362我正在尝试建立一个类似(整数)类型的编译时序列,仅使用模板元编程就可以将其存储在ROM中。 这个想法是通过使用模板元编程的可变方案逐行添加元素来逐步定义数组 目前我在这里: 我是模板元编程的
1回复

如何在编译时订购类型?

考虑以下程序: ordered帮助程序必须对一个元组中的类型进行重新排序,以使两个具有相同类型但元组的排序方式不同的元组导致相同的元组类型:可以是第一个,第二个甚至另一个:具有相同的大小和相同的元素,但是具有唯一的顺序(无论此顺序如何)。 是否可以使用模板元编程技术在编译时执行此操