mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
marking a field with noInit allows to skip constructor initialiser (#22802)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
@@ -28,7 +28,7 @@ slots when enlarging a sequence.
|
||||
|
||||
## Language changes
|
||||
|
||||
|
||||
- `noInit` can be used in types and fields to disable member initializers in the C++ backend.
|
||||
|
||||
## Compiler changes
|
||||
|
||||
|
||||
@@ -735,7 +735,8 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
else:
|
||||
# don't use fieldType here because we need the
|
||||
# tyGenericInst for C++ template support
|
||||
if fieldType.isOrHasImportedCppType() or hasCppCtor(m, field.owner.typ):
|
||||
let noInit = sfNoInit in field.flags or (field.typ.sym != nil and sfNoInit in field.typ.sym.flags)
|
||||
if not noInit and (fieldType.isOrHasImportedCppType() or hasCppCtor(m, field.owner.typ)):
|
||||
var initializer = genCppInitializer(m, nil, fieldType)
|
||||
result.addf("\t$1$3 $2$4;$n", [getTypeDescAux(m, field.loc.t, check, dkField), sname, noAlias, initializer])
|
||||
else:
|
||||
|
||||
@@ -72,9 +72,9 @@ const
|
||||
wIncompleteStruct, wCompleteStruct, wByCopy, wByRef,
|
||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||
wCppNonPod, wBorrow, wGcSafe, wPartial, wExplain, wPackage, wCodegenDecl,
|
||||
wSendable}
|
||||
wSendable, wNoInit}
|
||||
fieldPragmas* = declPragmas + {wGuard, wBitsize, wCursor,
|
||||
wRequiresInit, wNoalias, wAlign} - {wExportNims, wNodecl} # why exclude these?
|
||||
wRequiresInit, wNoalias, wAlign, wNoInit} - {wExportNims, wNodecl} # why exclude these?
|
||||
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
|
||||
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
|
||||
wNoInit, wCompileTime, wGlobal,
|
||||
|
||||
@@ -2408,6 +2408,56 @@ proc makeCppStruct(a: cint = 5, b:cstring = "hello"): CppStruct {.importcpp: "Cp
|
||||
# If one removes a default value from the constructor and passes it to the call explicitly, the C++ compiler will complain.
|
||||
|
||||
```
|
||||
Skip initializers in fields members
|
||||
===================================
|
||||
|
||||
By using `noInit` in a type or field declaration, the compiler will skip the initializer. By doing so one can explicitly initialize those values in the constructor of the type owner.
|
||||
|
||||
For example:
|
||||
|
||||
```nim
|
||||
|
||||
{.emit: """/*TYPESECTION*/
|
||||
struct Foo {
|
||||
Foo(int a){};
|
||||
};
|
||||
struct Boo {
|
||||
Boo(int a){};
|
||||
};
|
||||
|
||||
""".}
|
||||
|
||||
type
|
||||
Foo {.importcpp.} = object
|
||||
Boo {.importcpp, noInit.} = object
|
||||
Test {.exportc.} = object
|
||||
foo {.noInit.}: Foo
|
||||
boo: Boo
|
||||
|
||||
proc makeTest(): Test {.constructor: "Test() : foo(10), boo(1)".} =
|
||||
discard
|
||||
|
||||
proc main() =
|
||||
var t = makeTest()
|
||||
|
||||
main()
|
||||
|
||||
```
|
||||
|
||||
Will produce:
|
||||
|
||||
```c++
|
||||
|
||||
struct Test {
|
||||
Foo foo;
|
||||
Boo boo;
|
||||
N_LIB_PRIVATE N_NOCONV(, Test)(void);
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
Notice that without `noInit` it would produce `Foo foo {}` and `Boo boo {}`
|
||||
|
||||
|
||||
Member pragma
|
||||
=============
|
||||
|
||||
30
tests/cpp/tnoinitfield.nim
Normal file
30
tests/cpp/tnoinitfield.nim
Normal file
@@ -0,0 +1,30 @@
|
||||
discard """
|
||||
targets: "cpp"
|
||||
cmd: "nim cpp $file"
|
||||
output: '''
|
||||
'''
|
||||
"""
|
||||
{.emit: """/*TYPESECTION*/
|
||||
struct Foo {
|
||||
Foo(int a){};
|
||||
};
|
||||
struct Boo {
|
||||
Boo(int a){};
|
||||
};
|
||||
|
||||
""".}
|
||||
|
||||
type
|
||||
Foo {.importcpp.} = object
|
||||
Boo {.importcpp, noInit.} = object
|
||||
Test {.exportc.} = object
|
||||
foo {.noInit.}: Foo
|
||||
boo: Boo
|
||||
|
||||
proc makeTest(): Test {.constructor: "Test() : foo(10), boo(1)".} =
|
||||
discard
|
||||
|
||||
proc main() =
|
||||
var t = makeTest()
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user