我正在创建一个存储有关特定数据源的元数据的类.元数据以树形结构,与XML的结构非常相似.元数据值可以是整数,小数或字符串值.
我很好奇C++是否有一种很好的方法来存储这种情况的变体数据.我希望变体使用标准库,所以我避免使用可用的COM,Ole和SQL VARIANT类型.
我目前的解决方案看起来像这样:
enum MetaValueType
{
MetaChar,
MetaString,
MetaShort,
MetaInt,
MetaFloat,
MetaDouble
};
union MetaUnion
{
char cValue;
short sValue;
int iValue;
float fValue;
double dValue;
};
class MetaValue
{
...
private:
MetaValueType ValueType;
std::string StringValue;
MetaUnion VariantValue;
};
Run Code Online (Sandbox Code Playgroud)
MetaValue类具有各种Get函数,用于获取当前存储的变量值,但它最终使每个查询值成为if/else if语句的一大块,以确定我正在寻找的值.
我还探讨了将值存储为只有一个字符串,并执行转换以获得不同的变体类型,但据我所见,这会导致一堆内部字符串解析和错误处理,这不是很好,打开浮点值的精度和数据丢失问题很大,如果上面说的问题,仍然不会消除查询if/else.
是否有人使用标准库实现或看到了更清晰的用于C++变体数据类型的东西?
我很难在TR1文档中找到有关共享数组的参考资料.Boost文档非常明确,C++"new"和"new []"表达式之间存在显着差异.shared_ptr模板用于正确保存指向使用"new"创建的动态分配的对象的指针.shared_array模板用于使用"new []"正确保存指向动态分配的数组的指针.
我正在更新一些代码以使用TR1 shared_ptr模板和相关函数,但我没有发现shared_array.TR1 shared_ptr实现是否区分"new"和"new []",并正确销毁这些指针?据我所知,从TR1规格看,它似乎没有.如果是这种情况,我是否仍应使用boost shared_array模板进行"new []"样式分配?
使用boost :: filesystem :: exists时,我遇到了一些奇怪的情况.如果您尝试检查未准备好的驱动器上的文件是否存在或者没有介质,则会抛出basic_filesystem_error.至于我对bfs :: exists的大部分用法都很关注,如果驱动器没有准备好,则意味着该文件不存在.
我可以用try-catch包装我的调用以正确处理这个条件,但是它变得有点麻烦并且使代码有点笨拙.更糟糕的是,这意味着我正在使用basic_filesystem_error的特殊情况进行流控制,这意味着如果出现该异常的不同原因,我将不再适当地处理它.
出现这种情况的一般情况是,如果我尝试检查CD或DVD驱动器上是否存在文件.我以前的代码是:
if( bfs::exists( myFilePath ) )
{
...
}
Run Code Online (Sandbox Code Playgroud)
变为:
bool fileExists( false );
try
{
fileExists = bfs::exists( myFilePath );
}
catch( bfs::basic_filesystem_error<bfs::path> e )
{
fileExists = false;
}
if( fileExists )
{
...
}
Run Code Online (Sandbox Code Playgroud)
我并不太喜欢在我现有的代码库中进行这种改变的想法.
我正在考虑在某个地方创建一个单独的函数来包装try-catch并用它替换我的bfs :: exist调用,但我仍然不满意以这种方式使用try-catch是一个好主意.似乎我正在打开错过更重要和相关的特殊条件的大门.
我知道你可以为非抛出版本的函数重新编译boost,但我认为这并不能真正避免我的异常处理问题.
有没有人在使用可移动媒体驱动器之前遇到这个问题,如果是这样,你是如何克服它的?
我遇到了一个让我感到不安的问题.似乎我发现了一种容易解决的情况,但如果a)我在编程时失去了注意力,或者b)其他人开始实现我的界面并且不知道如何处理,这可能会导致问题这个情况.
这是我的基本设置:
我有一个抽象类,我正在使用它作为几种数据类型的通用接口.我采用了非虚拟公共接口范例(Sutter,2001)以及范围锁定来提供一些线程安全性.一个示例接口类看起来像这样(我省略了有关作用域锁定和互斥锁实现的细节,因为我不认为它们是相关的):
class Foo
{
public:
A( )
{
ScopedLock lock( mutex );
aImp( );
}
B( )
{
ScopedLock lock( mutex );
bImp( );
}
protected:
aImp( ) = 0;
bImp( ) = 0;
}
Run Code Online (Sandbox Code Playgroud)
然后由用户来实现aImp和bImp,这是问题所在.如果aImp执行一些使用bImp的操作,那么执行此操作非常容易(在某种意义上几乎是逻辑的):
class Bar
{
protected:
aImp( )
{
...
B( );
...
}
bImp( )
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
僵局.当然,对此的简单解决方案是始终调用受保护的虚拟函数而不是它们的公共变体(在上面的代码段中用bImp()替换B()).但是如果我犯了错误,或者更糟糕的是让其他人自己上吊,那么自己挂起来似乎仍然很容易.
有没有人有办法试图阻止抽象类的实现者在编译时调用那些公共函数,或者有助于避免死锁解决方案?
只是为了踢,一些互斥体允许操作,这将避免死锁问题.例如,如果我使用Windows函数EnterCriticalSection和LeaveCriticalSection实现它,则没有问题.但我宁愿避免使用特定于平台的功能.我目前在我的作用域锁实现中使用boost :: mutex和boost :: shared_mutex,据我所知,它并不试图避免死锁(我认为我几乎更喜欢).