Skip to content

Conversation

@Shizcow
Copy link
Contributor

@Shizcow Shizcow commented Sep 18, 2025

The current std::vector and std::deque wrappers define resize and subsequently call ::resize on the inner containers. This is an issue when value_type is not default construtable. For example:

struct NeverEmpty {
  int data;
  NeverEmpty() = delete;
  NeverEmpty(int d) : data(d);
};

using NeverEmptyVector = std::vector<NeverEmpty>;

Exposing bindings over NeverEmptyVector will call NeverEmptyVector::resize, which will unjustly generate a compiler error due to NeverEmpty not being default constructable.

This PR if constexpr gates the relevant ::resize calls behind a check to std::is_default_constructible_v. If value_type is not default constructable, bindings to ::resize are simply not generated.

While I was at it, I also tweaked the exposed append on std::vector to only call reserve if value_type is move insertable (as the standard requires).

Copy link
Contributor

@barche barche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Could you please also add a test to types.cpp that uses your NeverEmpty class in a method? Since this is preventing a compile error the method doesn't have to do anything not be called from the Julia side.

@Shizcow
Copy link
Contributor Author

Shizcow commented Sep 21, 2025

Thanks for the PR! Could you please also add a test to types.cpp that uses your NeverEmpty class in a method? Since this is preventing a compile error the method doesn't have to do anything not be called from the Julia side.

@barche I've added the test to types.cpp, and verified that compilation fails if the patch is removed.

While I did this, I also looked into the type trait rules for the std::vector and std::deque constructors, and decided to if constexpr gate those as well (for reasons documented in the diff). Note that while I was at this, I added three constructors: std::vector<T>(size_t), std::vector<T>(size_t, T), and std::deque<T>(size_t, T). These match the other constructors from the C++ STL. Of course, these are if constexpr gated with the relevant traits. I believe this was appropriate, but I'm open to discussion if I'm overstepping.

To support these three new constructors, is anything else required aside from the calls to wrapped.template constructor<...>()? I'm not familiar enough with this package to know if these will bubble up to the Julia level.

@Shizcow Shizcow changed the title Conditionally include resize methods depending on type traits Conditionally include resize methods / constructors depending on type traits Sep 21, 2025
namespace jlcxx
{
template<> struct IsMirroredType<cpp_types::DoubleData> : std::false_type { };
template<> struct IsMirroredType<cpp_types::NeverEmpty> : std::false_type { };
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why, specifically, is this required? There is a general lack of documentation on what exactly a mirrored type is. This compiles fine on my local machine without disabling mirroring for this type, but fails in the runners. Why? Is disabling mirroring correct here, or is the complaint indicative of an edge case I've not considered?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because this simple test class is detected as a "plain old data" type, and by default these are expected t be mapped to a Julia struct with the same layout, by using map_type instead of add_type. To override this, IsMirroredType can be specialized. Could be better documented, indeed :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that makes perfect sense. Thanks for the explanation!

@barche
Copy link
Contributor

barche commented Sep 23, 2025

Thanks for the PR, this is fine and the new constructors work.

@barche barche merged commit 007ef98 into JuliaInterop:main Sep 23, 2025
9 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants