是否有任何易于使用的,高层次的类或库,让你互动VARIANT的可视化(C S)++?
更具体地讲,我想POD类型(例如之间的转换double,long),字符串(如CString),和容器(如std::vector)和VARIANT秒.例如:
long val = 42;
VARIANT var;
if (ToVariant(val, var)) ... // tries to convert long -> VARIANT
comObjPtr->someFunc(var);
std::vector<double> vec;
VARIANT var = comObjPtr->otherFunc();
if (FromVariant(var, vec)) ... // tries VARIANT -> std::vector<double>
Run Code Online (Sandbox Code Playgroud)
我(天真地?)假设与COM一起工作的人一直这样做,所以最有可能是一个方便的库来处理各种转换.但是我能找到的所有内容都是各种各样的包装类,每个类都转换为几种类型:
有没有简单的方法 - 没有切换到Visual Basic - 以避免这种笨拙的内存管理和按位VT_ARRAY | VT_I4代码的噩梦?
相关问题: …
刚才在Delphi7工作,我注意到不仅VarIsEmpty存在一个函数,而且还存在一个函数VarIsEmptyParam.
由于Delphi的帮助没有给出太多解释:
如果给定的变量表示未分配的可选参数,则VarIsEmptyParam返回true.
如果变量包含任何其他值,则函数结果为false.
我只是想知道是否有人使用过这个功能,如果有的话,这个功能是如何使用的.
旧版本的Visual Basic中使用的OLE变体,在COM自动化中普遍存在,可以存储许多不同的类型:基本类型,如整数和浮点数,更复杂的类型,如字符串和数组,以及一直到IDispatch实现和指针形式的ByRef变种.
变量也是弱类型的:它们将值转换为另一种类型,而不会发出警告,具体取决于您应用的运算符以及传递给运算符的值的当前类型.例如,比较两个变体,一个包含整数1,另一个包含字符串"1",为了相等将返回True.
因此,假设我正在使用基础数据级别的变体(例如,VARIANT在C++或TVarDataDelphi中 - 即不同可能值的大联合),我应该如何一致地散列变体以使它们遵守正确的规则?
规则:
如果我必须使用不同的排序和直接比较规则以使哈希适合,那就没关系.
我正在工作的方式是我将变量规范化为字符串(如果它们适合),并将它们视为字符串,否则我正在使用变量数据,就像它是一个不透明的blob,并散列和比较它原始字节.当然,这有一些局限性:数字1..10排序[1, 10, 2, ... 9]等等.这有点令人讨厌,但它是一致的,而且工作很少.但是,我想知道这个问题是否有一个公认的做法.
渐渐地,我一直在使用更多变体 - 它们在某些地方非常有用,可以承载编译时未知的数据类型.一个有用的值是UnAssigned('我没有给你一个值').我想我很久以前就发现了这个功能:
function DoSomething : variant;
begin
If SomeBoolean then
Result := 4.5
end;
Run Code Online (Sandbox Code Playgroud)
似乎相当于:
function DoSomething : variant;
begin
If SomeBoolean then
Result := 4.5
else
Result := Unassigned; // <<<<
end;
Run Code Online (Sandbox Code Playgroud)
我推测这个推理必须动态创建一个变体,如果SomeBoolean为FALSE,编译器已创建它,但它是'Unassigned'(<> nil?).为了进一步鼓励这种思考,如果省略分配结果,编译器不会报告任何警告.
刚才我发现了令人讨厌的错误,我的第一个例子(其中'结果'未明确默认为'nil')实际上从其他地方返回了一个"旧"值.
在修复变体时,我是否应该总是分配结果(就像我在使用预定义类型时那样)?
普通的动态数组支持空(= nil, Length() = 0).
然而,变体阵列似乎不支持这一点.
我在变量数组中传递我的数据(因为OLE/COM),当用户定义0个元素时我得到一个错误...
我可以使用varEmpty而不是0长度数组,但这些数据数组是灵活更改的(添加项目,删除项目等).
我如何在Variant中传递空数组,还是需要使用其他方式?
我试图采用变量变量并将其转换为字符串,以便我可以对数据运行拆分函数.但是,每当我尝试重新定义变体时,我都会遇到类型不匹配错误.我使用了CStr(),Str()和ToString函数.没有工作.
我错过了什么?
Function FlatLine(ByVal lines As Variant)
Dim flat() As String
ReDim Preserve flat(i)
For i = 0 To UBound(lines)
flat(UBound(flat)) = lines(i)
ReDim Preserve flat(LBound(flat) To UBound(flat) + 1)
Next i
Dim flat2 as String
flat2 = Cstr(flat)
^ errors there.
Run Code Online (Sandbox Code Playgroud) 在一个变体类中,我正在处理原始存储是一个char数组:
alignas(/* the strictest alignment of all types of the variant */)
char storage[/* ... */];
Run Code Online (Sandbox Code Playgroud)
赋值运算符类似于:
template<class X>
void operator=(const X &x)
{
// ...code for clearing the storage and setting the tag for type X...
new(storage) X(x);
}
Run Code Online (Sandbox Code Playgroud)
获取存储对象的代码是:
template<class X>
const X &get()
{
// ...
return *reinterpret_cast<X *>(storage);
// ...
}
Run Code Online (Sandbox Code Playgroud)
它似乎工作,但它总是很好定义?我担心安全地解除引用指针(类型别名规则允许它吗?).
当前的实施和之间是否存在任何差异
return *static_cast<const X *>(static_cast<const void *>(storage));
Run Code Online (Sandbox Code Playgroud)
相关问题/答案:
/sf/answers/512527081/(见James Kanze的评论).
编辑
第二个问题已经有了答案:C++我们什么时候应该优先使用两个链式的static_cast而不是reinterpret_cast
这是我的问题:我想创建一个记录类型,其中在变体记录的情况下,一些(但不是全部)将具有某个字段.根据维基,这是完全合法的.然而,当我尝试编译以下代码时:
program example;
{$mode objfpc}{$H+}
uses sysutils;
type
maritalStates = (single, married, widowed, divorced);
TPerson = record
name: record
first, middle, last: string;
end;
sex: (male, female);
dob: TDateTime;
case maritalStatus: maritalStates of
single: ( );
married, widowed: (marriageDate: TDateTime);
divorced: (marriageDate, divorceDate: TDateTime;
isFirstDivorce: boolean)
end;
var
ExPerson: TPerson;
begin
ExPerson.name.first := 'John';
ExPerson.name.middle := 'Bob';
ExPerson.name.last := 'Smith';
ExPerson.sex := male;
ExPerson.dob := StrToDate('05/05/1990');
ExPerson.maritalStatus := married;
ExPerson.marriageDate := StrToDate('04/01/2015');
end.
Run Code Online (Sandbox Code Playgroud)
编译失败,出现以下错误:
$ fpc ex.pas
Free …Run Code Online (Sandbox Code Playgroud) 我想知道std::visit返回类型转换应该如何工作.
上下文如下:我有一个变体对象,我想std::visit根据它的底层类型应用(通过)不同的函数.每个函数的结果可能有不同的类型,但我希望std :: visit将其打包为变体类型.
伪代码:
我有:
variant<A,B> obj
f(A) -> A
f(B) -> B
Run Code Online (Sandbox Code Playgroud)
我想要:
if obj is of type A => apply f(A) => resA of type A => pack it in variant<A,B>
if obj is of type B => apply f(B) => resB of type B => pack it in variant<A,B>
Run Code Online (Sandbox Code Playgroud)
现在,根据cppreference,std :: visit的返回类型是"所选访问者调用返回的值,转换为所有可能的std :: invoke表达式的公共类型"但是没有指定常见类型的含义.是std::common_type吗?在这种情况下,它不适用于gcc 7.2:
#include <variant>
#include <iostream>
#include <type_traits>
struct A {
int i;
};
struct …Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
#include <variant>
struct x {
int y;
};
int main() {
std::variant<x> v(std::in_place_type<x>, {3}); /*1*/
return std::get<x>(v).y;
}
Run Code Online (Sandbox Code Playgroud)
即使聚合初始化,这也不会编译,也不会{}从行中删除/*1*/
x a{3};
x b({3});
Run Code Online (Sandbox Code Playgroud)
适用于"类似构造函数"的形式.我可以以某种方式使std::variant初始化器知道使用聚合初始化构造结构的可能性,而不必为我的实际案例中可能使用的每个结构编写无聊的样板构造函数吗?
我希望这可以工作,不知何故,根据cppreference,有问题的两个重载(5)和(6)都说
使用指定的替代T构造变量并使用参数[...] 初始化包含的值
如果重要的话,我正在使用GCC 7.