为啥c++的set容器的自定义比较函数要用一个结构体重载()符
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥c++的set容器的自定义比较函数要用一个结构体重载()符相关的知识,希望对你有一定的参考价值。
struct comp
bool operator()(const int &a,const int &b)
if(a!=b)
return a>b;
else
return a>b;
;
问题比较绕口,请大牛们悉心指点。本人很笨。
template<class T, class C, class A> class set;
第一个T 是元素类型,必选;
第二个C 指定元素比较方式,缺省为 Less<T>, 即使用 < 符号比较;
第三个A 指定空间分配对象,一般使用默认类型。
因此:
(1) 如果第2个泛型参数你使用默认值的话,你的自定义元素类型需要重载 < 运算操作;
(2)如果你第2个泛型参数不使用默认值的话,则比较对象必须具有 () 操作,即:
bool operator()(const T &a, const T &b)
以上。 参考技术A 你这种方法相当是定义了一个函数对象,用自定义一个比较函数也可以地 参考技术B 谁说的?
没必要。
为啥 autorest 用 Swagger 中的对象替换我的自定义结构?
【中文标题】为啥 autorest 用 Swagger 中的对象替换我的自定义结构?【英文标题】:Why autorest is replacing my custom struct by an object in Swagger?为什么 autorest 用 Swagger 中的对象替换我的自定义结构? 【发布时间】:2021-09-06 01:51:49 【问题描述】:我创建了一个自定义的readonly
struct
来定义我称之为TenantId
的不可变值类型:
[DebuggerDisplay("ID=m_internalId.ToString()")]
[JsonConverter(typeof(TenantIdJsonConverter))]
public readonly struct TenantId : IEquatable<TenantId>
private readonly Guid m_internalId;
public static TenantId New => new(Guid.NewGuid());
private TenantId(Guid id)
m_internalId = id;
public TenantId(TenantId otherTenantId)
m_internalId = otherTenantId.m_internalId;
...
我还定义了一个名为 PurchaseContract
的合同,它是 HTTP 响应的一部分:
[JsonObject(MemberSerialization.OptIn)]
public sealed class PurchaseContract
[JsonProperty(PropertyName = "tenantId")]
public TenantId TenantId get;
[JsonProperty(PropertyName = "total")]
public double Total get;
最后,我设置了一个 HTTP 触发函数,它将返回一个 PurchaseContract
的实例。目前,已经在ProducesResponseTypeAttribute
进行了描述:
[ApiExplorerSettings(GroupName = "Purchases")]
[ProducesResponseType(typeof(PurchaseContract), (int) HttpStatusCode.OK)]
[FunctionName("v1-get-purchase")]
public Task<IActionResult> RunAsync
(
[HttpTrigger(AuthorizationLevel.Anonymous, "GET", Route = "v1/purchases")]
HttpRequest httpRequest,
[SwaggerIgnore]
ClaimsPrincipal claimsPrincipal
)
// Stuff to do.
return Task.FromResult((IActionResult)new OkResult());
在我的Startup
课程中,我正在设置这样的招摇:
private static void ConfigureSwashBuckle(IFunctionsHostBuilder functionsHostBuilder)
functionsHostBuilder.AddSwashBuckle(Assembly.GetExecutingAssembly(), options =>
options.SpecVersion = OpenApiSpecVersion.OpenApi3_0;
options.AddCodeParameter = true;
options.PrependOperationWithRoutePrefix = true;
options.XmlPath = "FunctionApp.xml";
options.Documents = new []
new SwaggerDocument
Title = "My API,
Version = "v1",
Name = "v1",
Description = "Description of my API",
;
);
在swagger UI页面中,我可以看到它看起来不错:
问题
使用 Autorest 创建 C# 客户端时出现意外结果。不知何故,TenantId
结构被删除并替换为object
:
为什么会这样?我应该怎么做才能自动生成 TenantId
,就像客户端中的 PurchaseContract
一样?
详情
这是版本信息。
在netcore3.1上运行的Function App V3; OpenApi 3.0; Autorest Core 3.0.6274、autorest.csharp' (~2.3.79->2.3.91) 和 autorest.modeler' (2.3.55->2.3.55); NuGet 包AzureExtensions.Swashbuckle;【问题讨论】:
【参考方案1】:我开始研究Swashbuckle.AspNetCore.SwaggerGen 的源代码,以了解我的readonly
struct
是如何被解释的。这一切都发生在JsonSerializerDataContractResolver 类中,在方法@987654328@ 中,该方法为提供的类型确定DataContract
:
public DataContract GetDataContractForType(Type type)
if (type.IsOneOf(typeof(object), typeof(JsonDocument), typeof(JsonElement)))
...
if (PrimitiveTypesAndFormats.ContainsKey(type))
...
if (type.IsEnum)
...
if (IsSupportedDictionary(type, out Type keyType, out Type valueType))
...
if (IsSupportedCollection(type, out Type itemType))
...
return DataContract.ForObject(
underlyingType: type,
properties: GetDataPropertiesFor(type, out Type extensionDataType),
extensionDataType: extensionDataType,
jsonConverter: JsonConverterFunc);
我的自定义 struct
TenantId
不符合这些条件中的任何一个,因此,它回退到被视为 object
(最后一条语句)。
然后我继续查看现有的tests,以了解该类的使用情况,看看我是否可以更改任何内容。令人惊讶的是,我发现了一个名为 GenerateSchema_SupportsOption_CustomTypeMappings
的测试(第 356 行),它显示了一种提供自定义映射的方法(参见该方法的第一条语句):
[Theory]
[InlineData(typeof(ComplexType), typeof(ComplexType), "string")]
[InlineData(typeof(GenericType<int, string>), typeof(GenericType<int, string>), "string")]
[InlineData(typeof(GenericType<,>), typeof(GenericType<int, int>), "string")]
public void GenerateSchema_SupportsOption_CustomTypeMappings(
Type mappingType,
Type type,
string expectedSchemaType)
var subject = Subject(configureGenerator: c => c.CustomTypeMappings.Add(mappingType, () => new OpenApiSchema Type = "string" ));
var schema = subject.GenerateSchema(type, new SchemaRepository());
Assert.Equal(expectedSchemaType, schema.Type);
Assert.Empty(schema.Properties);
就我而言,我想让我的TenantId
映射到string
。为此,我在 Function App 启动时编辑了 SwashBuckle 的配置:
private static void ConfigureSwashBuckle(IFunctionsHostBuilder functionsHostBuilder)
functionsHostBuilder.AddSwashBuckle(Assembly.GetExecutingAssembly(), options =>
...
options.ConfigureSwaggerGen = (swaggerGenOptions) => swaggerGenOptions.MapType<TenantId>(() => new OpenApiSchema Type = "string");
);
就是这样,TenantId
现在在 Swagger 中被视为 string
。
【讨论】:
以上是关于为啥c++的set容器的自定义比较函数要用一个结构体重载()符的主要内容,如果未能解决你的问题,请参考以下文章