实际上,主要问题仍然是 Kotlin 中的类没有具体化的类型参数。但这就是为什么在这个特定情况下这让我感到困扰:
假设您有一个包装类Wrapper,它接受一个字符串content和一个类* ,并且可以通过调用函数按需解析为 JSON 来输出检索到的type类的对象:typecontentgetObj()
class Wrapper<T>(private val content: String, /*private val type: KClass<*>*/) {
fun getObj(): T {
// ?
}
}
Run Code Online (Sandbox Code Playgroud)
我想使用 kotlinx.serialization。现在,你可能已经注意到我之前是如何在“class”后面加星号的。原因是:是的,Wrapper必须以某种方式参加目标课程,但是如何呢?它应该只是 typearg (不起作用,因为类型erausre)还是引用KClass(不起作用,因为我需要具体化的 typearg)?
事实是,据我所知,将通用 JSON 解码为可序列化目标类的唯一方法是使用Json.decodeFromString<T>(content),其中T是目标类型,content是 JSON 字符串。现在,T被定义为具体化(以便可以在运行时处理类型)并且只能用另一个具体化的 typearg 或实际的类引用来填充。我无法使用另一个具体化的类型参数,因为我处于类的上下文中,并且类不能具有具体化的类型参数。我也不能使用实际的类引用,因为类的用户应该能够使用不同的目标来构造它,例如他们决定目标是什么,而不是我。
那么,我该如何使用 kotlinx.serialization 来做到这一点?有可能吗?
generics json kotlin kotlin-reified-type-parameters kotlinx.serialization
因此,我一直在致力于Vector一项作业的实现,并在实现迭代器时注意到一些奇怪的 Clang-Tidy 建议。
根据要求的规范,迭代器必须具有iterator& operator++()和重载。iterator operator++(int)现在,当我尝试定义iterator operator++(int),它本质上是复制迭代器,递增指针,然后返回该副本,Clang-Tidy 抱怨道:
重载的“operator++”返回一个非常量对象而不是常量对象类型
(显然)应该通过将返回类型更改为 来解决这个问题const iterator,否则这种技术非常罕见。不过,相应地更改签名会让 Clang-Tidy 再次抱怨:
返回类型“const Vector::iterator”(又名“const Vector::Iterator”)在顶层具有“const”限定,这可能会降低代码可读性,而不会提高 const 正确性
CLion 2020.3.2 中的默认修复操作实际上删除了const,这会带回原始的 Clang-Tidy 警告。
我想知道什么是“正确”的实施方式operator++(int)。在这种情况下我应该忽略 Clang-Tidy 吗?如果是,我应该选择哪个签名?
谢谢!
编辑1
以下帖子没有回答我的问题:Other StackOverflow Question。事实上,在我决定问自己的问题之前我就看到了这篇文章,因为它没有为我解答。问题是在链接的帖子中建议了两个选项:
- 按照 clang-tidy 所说的去做,但可能会失去移动语义的好处。
- 相反,左值引用限定重载,以模仿小整数。
(1) 的意思正是我所做的,即将 a 放在返回类型const前面iterator。正如我在帖子中所述,这会触发第二个 Clang-Tidy 警告。
(2) 不消除 Clang-Tidy 警告。我也不确定我是否可以在作业的限制下使用它。
另外,这是一个最小的可重现示例:
class Iterator {
ptr_type ptr; // whatever your pointer type is …Run Code Online (Sandbox Code Playgroud) 我在使用不同编码器比较两个字符串时遇到了问题。我的代码实际上是用 Kotlin 编写的,但它在 JVM 上运行,并且有效地使用了 Java 的 String 实现。另外,我的问题具有更普遍的性质,我的实际代码不会受到关注。
\n问题是我有两个字符串,比如说a和b,其中
a = "something something \xc3\xa4\xc3\xb6\xc3\xbc something"\nb = "\xc3\xa4\xc3\xb6\xc3\xbc"\nRun Code Online (Sandbox Code Playgroud)\n您期望a.contains(b)返回true,如果您像上面所示检索字符串,情况就是如此。但就我而言,字符串来自不同的来源,并且碰巧有不同的编码器。Stringa有编码器1,即UTF16,并且 Stringb有编码器0,即LATIN1。在这种情况下,a.contains(b)返回 false。现在您可能已经注意到我包含了特殊字符(\xc3\xa4、\xc3\xb6和\xc3\xbc),因为根据我的调试,这就是比较失败的地方。
当我位于a.contains(b)发生调用的堆栈帧时,两个字符串都正确显示在我的调试器 (IntelliJ IDEA Ultimate 2020.2) 中。但是,如果我随后进入比较函数,我注意到在java.lang.StringLatin1.regionMatchesCI_UTF16()字节数组逐字符转换回的位置,特殊字符b现在不正确(\xc3\xa4-> a、\xc3\xb6-> o、\xc3\xbc-> u)。当然,这样比较就失败了。
现在正如我所说,两个字符串最初都在调试器中正确显示,因此信息必须位于某处。我的问题是:我必须做什么才能让呼叫按预期a.contains(b) …
kotlin ×2
c++ ×1
clang-tidy ×1
contains ×1
generics ×1
java ×1
json ×1
kotlin-reified-type-parameters ×1
string ×1