我正在尝试创建一个类系统,这些类是小对象,基类有一个成员,它是标识该类的唯一标识符:
class Shape
{
public:
unsigned char id;
};
template <typename T>
class Triangle : public Shape
{
T triangle_data;
};
template <typename T>
class Square : public Shape
{
T square_data;
};
template <typename T>
class ShapeBox : public Shape
{
T shapebox_data;
Shape * child_shape;
};
使用类标识符,我遍历 Shape * 的 vector 并打开在基类中可见的 id,然后针对不同的行为进行静态转换(针对三角形、正方形或 ShapeBox 以及分别包含在其中的子形状)示例类层次结构)
我可以打开 RTTI,但空间成本似乎相当大,尤其是当类型信息可以实现为指针并且对象大小可能不超过几个字节时。可能有数百万个小对象,无论如何我真的只需要静态转换。
目前我可以通过使用从静态单调递增计数器分配值的静态来创建类型标识符:
class TypeID
{
static size_t counter;
public:
template<typename T>
static size_t value()
{
static size_t id = counter++;
return id;
}
};
size_t TypeID::counter = 1;
理想情况下,我想要在编译时可用的密集、唯一的类型 ID,这样编译器就可以很好地执行,例如将类型 ID 上的开关转换为恒定时间跳转表,或者至少是二叉搜索树而不是可能是一长串类型 ID 的线性时间 if/else 链...
我可以在编译时使用样板文件手动分配每个类型 ID,或者我可以使用来自类似类型 ID 类的对象/函数指针。保证样板是密集的(因为我们手动分配它)并且在编译时已知,但它对于模板类型是不可维护的。无论何时向形状添加模板类型,都必须手动添加新类型。单调静态计数器是可维护和密集的,但在编译时是未知的,因此编译时优化是不可能的,并且线程安全可能是一个问题。函数指针 ID 在编译时已知且可维护,但不密集且不适合像 char 这样的小型 ID 类型。
有没有办法生成编译器在编译时可见的、密集的和自动分配的类型 ID,也许使用模板元编程计数器或 C++11 或 C++14 中的一些预处理器魔法?或者这在 C++ 具有编译时反射之前是不可能的吗?
最佳答案
Is there any way to generate type IDs that are visible to the compiler at compile time, dense, and automatically assigned, perhaps using template metaprogramming counter
我开发了一个代码,它几乎没有限制。
两个模板特化 ID_by_T和 T_by_ID定义 type <=> ID编译时链接。类型的 ID 是一个枚举常量。如果type <=> ID链接未定义ID_by_T<type>::ID是-1和 T_by_ID<undefinedID>::type是null_t预定义类型。 DEF_TYPE_ID(type_name)宏在定义 type <=> ID 时生成新 ID关联。 int_triangle和 char_triangle显示如何使用正确的类型 ID 和内部 typedef 获取 typedef _MyID_T显示如何获取类型的 ID。代码使用 MS VS 2005 C++ 编译。
核心——type_id_map头文件:
#ifndef __TYPE_ID_MAP__
#define __TYPE_ID_MAP__
namespace ns_type_ids {
struct null_t {};
template<class T, int ID_v>
struct ID_T_pair {
enum {ID=ID_v};
typedef T _Type;
inline static const _TCHAR * name() { return _T("unknown"); }
};
template<class T> struct ID_by_T: ID_T_pair<T, -1> {};
template<int ID_v> struct T_by_ID: ID_T_pair<null_t, ID_v> {};
template<> struct ID_by_T<null_t>: ID_T_pair<null_t, -1> {
inline static const _TCHAR * name() { return _T("null_t"); }
};
template<> struct T_by_ID<ID_by_T<null_t>::ID>: ID_by_T<null_t> {};
};
#define PREV_TYPE null_t
#define DEF_TYPE_ID(type_name) \
namespace ns_type_ids { \
template<> struct ID_by_T<type_name>: ID_T_pair<type_name, ID_by_T<PREV_TYPE>::ID+1> { \
inline static const _TCHAR * name() { return _T(#type_name); } \
}; \
template<> struct T_by_ID<ID_by_T<type_name>::ID>: ID_by_T<type_name> {}; \
};
#endif
以及 type_id_map 在 templated_cls_id.cpp 中的使用示例:
#include <tchar.h>
#include <iostream>
#ifdef _UNICODE
#define _tcout wcout
#else
#define _tcout cout
#endif
#include "type_id_map"
//targeted types
struct shape {};
template<class T>
struct data_t: shape {
T _data;
};
template<class T>
struct triangle: data_t<T>, ns_type_ids::ID_by_T<data_t<T> > {
typedef data_t<T> _MyID_T;
};
//begin type <=> id map
DEF_TYPE_ID(int)
#undef PREV_TYPE
#define PREV_TYPE int
DEF_TYPE_ID(double)
#undef PREV_TYPE
#define PREV_TYPE double
DEF_TYPE_ID(float)
#undef PREV_TYPE
#define PREV_TYPE float
DEF_TYPE_ID(data_t<int>)
#undef PREV_TYPE
#define PREV_TYPE data_t<int>
DEF_TYPE_ID(data_t<char>)
#undef PREV_TYPE
#define PREV_TYPE data_t<char>
//end type <=> id map
//Now targeted classes could be defined
typedef triangle<int> int_triangle;
typedef triangle<char> char_triangle;
int _tmain(int argc, _TCHAR* argv[]) {
using namespace std;
using namespace ns_type_ids;
#define out_id(type_name) \
_T("ID_by_T<") _T(#type_name) _T(">::ID: ") << ID_by_T<type_name>::ID
#define out_name(type_id) \
_T("T_by_ID<") _T(#type_id) _T(">: ") << T_by_ID<type_id>::name()
_tcout
<< out_id(null_t) << endl
<< out_id(int) << endl
<< out_id(double) << endl
<< out_id(float) << endl
<< out_id(int_triangle::_MyID_T) << endl
<< out_id(char_triangle::_MyID_T) << endl
<< out_name(-1) << endl
<< out_name(0) << endl
<< out_name(1) << endl
<< out_name(2) << endl
<< out_name(3) << endl
<< out_name(4) << endl
;
return 0;
#undef out_id
#undef out_name
}
输出:
ID_by_T<null_t>::ID: -1
ID_by_T<int>::ID: 0
ID_by_T<double>::ID: 1
ID_by_T<float>::ID: 2
ID_by_T<int_triangle::_MyID_T>::ID: 3
ID_by_T<char_triangle::_MyID_T>::ID: 4
T_by_ID<-1>: null_t
T_by_ID<0>: int
T_by_ID<1>: double
T_by_ID<2>: float
T_by_ID<3>: data_t<int>
T_by_ID<4>: data_t<char>
要求和限制:
Type <=> ID map 是全局的,仅在编译时有效。Type <=> ID必须使用 DEF_TYPE_ID 在全局命名空间级别定义链接和 PREV_TYPE宏观。Type <=> ID 之前声明“IDed”类型链接。ID_by_T<self_type>作为基类,其中 self_type 是自己的类类型。但为什么(见下文)?ID_by_T<base_data_type>作为基类,其中 base_data_type 是模板类的特殊基类型,用于 type <=> ID链接已经定义。参见 int_triangle和 char_triangle例如。还有其他技巧可以在模板实例中获取定义的 ID。特点
type <=> ID 的编译顺序中从 0 开始链接定义。由于问题的需要,这是必然的。ISO/IEC 14882:2003 SE 的标准功能.__COUNTER__ , __LINE__ , BOOST_PP_COUNTER 或基于 sizeof不用于分配 ID:它们没有副作用。type <=> id map 基于编译时已知的外部 ID:
ID_T_pair模板描述 type <=> id关联。 ID_by_T/T_by_ID模板是 ID_T_pair 的直接后代模板。ID_by_T模板没有必要在类型内部定义 ID(基本类型不可能做到这一点)。ID_by_T<type>::ID枚举常量。T_by_ID<ID>::_Type 访问 ID 类型内部类型定义。name() 访问类型的名称ID_T_pair的方法| .name(),映射不占用任何内存字节的 ID_T_pair未使用。type <=> id链接可以在全局命名空间级别就地定义。null_t和 ID=-1在没有 type <=> ID 的情况下返回链接。关于c++ - 如何在编译时生成密集的唯一类型 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26570904/
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"