Skip to content

[C++] sizeof on opaque importcpp template parameter prevents using C++ template defaults like sizeof(T) #25805

@puffball1567

Description

@puffball1567

Description

When a C++ template uses sizeof(T) in its default arguments, the corresponding Nim binding cannot use that default because Nim's sizeof on opaque importcpp template parameters requires .completeStruct, which is semantically incompatible with opaque types.

Minimal Repro

{.emit: """/*TYPESECTION*/
template<typename T, int N = 1024 / sizeof(T) + 8>
struct Buf {
  T data[N];
};
""".}

type
  # Naive binding emits the default as-is:
  Buf*[T; N: static cint = 1024 div sizeof(T) + 8] {.importcpp: "Buf<'0, '1>".} = object

proc main() =
  var x: Buf[cint]   # cannot use C++-side default

main()

Result:

Error: 'sizeof' requires '.importc' types to be '.completeStruct'

If we strip the default to side-step the error:

type
  Buf*[T; N: static cint] {.importcpp: "Buf<'0, '1>".} = object

proc main() =
  var x: Buf[cint]   # Error: cannot instantiate Buf, got: <typedesc[cint]>, but expected: <T, N>

So the C++-side default is effectively dead either way.

Impact

sizeof(T) in template defaults is a common pattern in C++ libraries (containers, buffers, etc.). When writing Nim bindings, these defaults cannot be honored:

  • The user is forced to specify the second template parameter every time (Buf[float, 1024] instead of Buf[float]).
  • The "use it like the C++ documentation says" experience breaks.
  • It is not possible to express the default in any equivalent way on the Nim side, so this becomes a hard expressivity gap of importcpp template defaults.

It would be useful if either:

  1. Nim allowed sizeof on opaque importcpp template params for template-default purposes (the value is resolved at C++ instantiation time anyway), or
  2. Nim allowed declaring a generic param without a default such that omission falls through to the underlying C++ template default during importcpp instantiation.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions