首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >元功能将类型转换为整数,反之亦然。

元功能将类型转换为整数,反之亦然。
EN

Stack Overflow用户
提问于 2015-12-11 18:26:58
回答 3查看 2.1K关注 0票数 8

typeid允许在运行时为每个类型分配唯一的std::type_index。我也想做同样的事情,静态地使用两个元功能:

代码语言:javascript
复制
// Get a unique integral number associated with the provided type
template <class T>
struct encode_type
{
    using type = T;
    static constexpr std::size_t value = /* Metaprogramming magic */;
};

// Get the type uniquely associated with the provided value
template <std::size_t V>
struct decode_type
{
    static constexpr std::size_t value = V;
    using type = /* Metaprogramming magic */;
};

在C++11中有办法做到这一点吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-12-16 10:51:12

下面是GCC 5.2和Clang 3.7的一个可能的解决方案。

我使用菲利普·罗塞恩Constexpr元容器做了一些轻微的改动。正如T.C.指出的那样,这在将来可能是使畸形,所以这个解决方案在生产代码中是完全不合理的,但目前它相当酷。我甚至不确定这是否100%符合标准--符合标准。

代码语言:javascript
复制
// This is our meta-container
using TypeMap = atch::meta_list<class A>;

// Get a unique integral number associated with the provided type
template <class T>
struct encode_type
{
    using type = T;
    // Push T into the container and store the pre-push size
    //( requires slight change to Filip's code)
    static constexpr std::size_t value = TypeMap::push<T>();
};

// Get the type uniquely associated with the provided value
template <std::size_t V>
struct decode_type
{
    static constexpr std::size_t value = V;
    // Get the type at index V
    // (requires a small helper function addition)
    using type = decltype(TypeMap::at<V>());
};

我对原始代码所做的修改:

代码语言:javascript
复制
template<class T, class H = meta_list, std::size_t Size = counter::value()>
static constexpr std::size_t push (
  size_type = push_state<
    typename H::template value<>::template push<T>::result
  > ()
) { return Size; } 

我修改了atch::meta_list::push以在推送之前返回元容器的大小。我使用了一个带有默认参数的模板参数,以确保在推送之前计算大小。

代码语言:javascript
复制
template<size_type Idx, class H = meta_list>
static constexpr auto at () -> typename H::template value<>::template at<Idx>::result;

我在decltype中添加了一个小的atch::meta_list助手函数,以隐藏所有依赖的名称混乱。

一些测试代码:

代码语言:javascript
复制
int main () {
    std::array<int, 4> encoded { 
        encode_type<int>::value,
        encode_type<double>::value,
        encode_type<std::string>::value,
        encode_type<float>::value
    };
  
  std::cout << "Encoding: ";
  for (auto i : encoded) std::cout << i << ", ";
  std::cout << std::endl;
  
  std::array<std::type_index, 4> decoded {
      typeid(decode_type<0>::type),  
      typeid(decode_type<1>::type),
      typeid(decode_type<2>::type),
      typeid(decode_type<3>::type),
  };
  
  std::cout << "Decoding: ";
  for (auto i : decoded) std::cout << i.name() << ", ";
  std::cout << std::endl;
}

Clang和GCC都说了一堆警告,但他们都“成功”了!

Clang 编译、运行和输出

编码: 0,1,2,3, 解码: i,d,NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE,f,

GCC 编译、运行和输出

编码: 0,1,2,3, 解码: i,d,NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE,f,

也许你最好先做个预处理.

票数 8
EN

Stack Overflow用户

发布于 2015-12-11 19:48:57

C++中的类型多于size_t所能计算的类型。

作为证据:

代码语言:javascript
复制
template<size_t N> struct bob {};

bob<X>类型与size_t值完全相同。

代码语言:javascript
复制
template<class...> struct alice {};

现在,alice<bob<1>, bob<2>>是一个有效的类型。alice<alice<bob<1>>也是。

alice类型比bob类型多很多。

因此,不存在从size_t值集到类型集的注入。

因此,任何这样的映射都必须是不完整的,如果是双射的。您只能将某些类型的子集映射到size_t并再次返回。

您没有指定只想处理类型的子集,所以答案是,您不能按要求执行。

请注意,std::type_index只是一个可连接的、可比较的对象。它不是像整数值那样的“索引”。

票数 4
EN

Stack Overflow用户

发布于 2015-12-15 15:57:47

我会给出一个部分的解决方案,因为我对解决所有混乱的细节不感兴趣。使用接受包含整个类型定义的参数的宏。现在用这个参数做三件事(需要有助手宏):

  • 使用参数作为-is来定义类型。
  • 将字符串化的参数传递给加密散列函数。
    • 该函数的输出将是若干位数的整数。毫无疑问,由于是加密安全的,该整数将大于内置的整数类型。所以,不要使用type_idsize_t之类的,而是使用您自己的索引类型;它可以是POD。

  • 该哈希函数的值是定义encode_typedecode_type的神奇值。
    • 由于模板参数中类型的限制,您可能必须使用保存哈希值的constexpr存储的地址来定义decode_type

这里的基本原理与G del证明其不完全性定理的原理相同,即一串字符总是有两种解释,一种是形式系统的成员,另一种是数字。(顺便提一句,证据的核心是创造一种在正式系统中谈论这个数字的方式。)

当然,使用C++工具链中现成的工具的细节是混乱的。但是,使其成为可能的关键元素是字符串化操作符#。这类似于上文的第二种解释,即定义不是作为一种语言的成员,而是作为“公正的数据”。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34230174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档