Skip to content

Array, Grid の推論補助を追加 #1309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: v6_develop
Choose a base branch
from

Conversation

Raclamusi
Copy link
Member

#1307 の修正と、機能追加です。

追加される機能

  • 新たに以下のコンストラクタで CTAD が効くようになります
    • Array(size_type count, const value_type& value, const Allocator& alloc = Allocator{})
    • Array(size_type size, Arg::generator_<Fty> generator)
    • Array(size_type size, Arg::indexedGenerator_<Fty> indexedGenerator)
    • Grid(size_type w, size_type h, const value_type& value)
    • Grid(Size size, const value_type& value)
    • Grid(size_type w, size_type h, Arg::generator_<Fty> generator)
    • Grid(Size size, Arg::generator_<Fty> generator)
    • Grid(size_type w, size_type h, Arg::indexedGenerator_<Fty> indexedGenerator)
    • Grid(Size size, Arg::indexedGenerator_<Fty> indexedGenerator)
  • Issue では const value_type& を引数に取るコンストラクタについて問題提起しましたが、この問題を解決するにあたって Arg::generatorArg::indexedGenerator を考慮する必要があったので、一緒に Arg::generatorArg::indexedGenerator を取るコンストラクタでも CTAD が効くようにしました
  • この PR で Grid g(2, 2, Array<int, Allocator<int>>{}) のようなコードが有効になってしまいます
    • コンストラクタ Grid(size_type w, size_type h, const Array<value_type>& data) の引数 dataGrid::allocator_type にかかわらずデフォルトのアロケータを使用する Array であり、 Array<int, Allocator<int>> などの値は渡せません
    • 変更前はエラーでしたが、変更後は以下のように CTAD が非直感的に働く可能性があります
    • Array<int> a1{ 3, 1, 4, 1 };
      Array<int, Allocator<int>> a2{ 3, 1, 4, 1 };
      Grid g1(2, 2, a1);  // Grid<int> に推論される
      Grid g2(2, 2, a2);  // Grid<Array<int, Allocator<int>>> に推論される(!)

実装

  • Array.hpp, Grid.hpp に推論補助を追加しました
  • 追加した推論補助 Array(typename Array<Type, Allocator>::size_type, const Type&, const Allocator& = Allocator{}) -> Array<Type, Allocator> には以下のような問題があったため、 std::is_same_v<typename Allocator::value_type, Type> でこの推論補助を制約しています
    • std::list<int> list{ 3, 1, 4, 1 };
      Allocator<int> alloc;
      Array a(list.begin(), list.end(), alloc);  // Array<std::list<int>::iterator, Allocator<int>> に推論され、コンパイルエラー
  • 追加した推論補助 Array(typename Array<Type, Allocator>::size_type, const Type&, const Allocator& = Allocator{}) -> Array<Type, Allocator> および対応する Grid の推論補助には以下のような問題があったため、 not detail::IsNamedParameter_v<Type> でこれらの推論補助を制約しています
    • Array a(3, Arg::generator = [] { return 42; });  // Array<Arg::generator_<...>> に推論される
      Grid g1(2, 2, Arg::generator = [] { return 42; });  // Grid<Arg::generator_<...>> に推論される
      Grid g2(Size{ 2, 2 }, Arg::generator = [] { return 42; });  // Grid<Arg::generator_<...>> に推論される
    • detail::IsNamedParameter_v を定義し、面倒だったので Arg::generator, Arg::indexedGenerator だけでなくすべての NamedParameter を弾いています
    • detail::IsNamedParameter_v の定義は少し変なところに置いており、適切ではないかもしれません

テストコード

# include <Siv3D.hpp> // Siv3D v0.6.16

struct ArrayIsh
{
	const Array<int, Allocator<int>>& asArray() const;
};

static_assert(requires (
	Array<int, Allocator<int>> a,
	std::vector<int, Allocator<int>> v,
	Allocator<int> alloc)
{
	{ Array(a)            } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(std::move(a)) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(v)            } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(std::move(v)) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(3, 42)        } -> std::same_as<Array<int>>;
	{ Array(3, 42, alloc) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(a.begin(), a.end())        } -> std::same_as<Array<int>>;
	{ Array(a.begin(), a.end(), alloc) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(a)                   } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(a, alloc)            } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(std::move(a))        } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(std::move(a), alloc) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(v)                   } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(v, alloc)            } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(std::move(v))        } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(std::move(v), alloc) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array({ 42, 42, 42 })        } -> std::same_as<Array<int>>;
	{ Array({ 42, 42, 42 }, alloc) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(ArrayIsh{}) } -> std::same_as<Array<int, Allocator<int>>>;
	{ Array(3, Arg::generator = [] { return 42; }) } -> std::same_as<Array<int>>;
	{ Array(3, Arg::indexedGenerator = [](size_t) { return 42; }) } -> std::same_as<Array<int>>;
});

static_assert(requires (
	Grid<int, Allocator<int>> g,
	Array<int> a,
	Allocator<int> alloc)
{
	{ Grid(g)            } -> std::same_as<Grid<int, Allocator<int>>>;
	{ Grid(std::move(g)) } -> std::same_as<Grid<int, Allocator<int>>>;
	{ Grid(2, 2, 42) } -> std::same_as<Grid<int>>;
	{ Grid(Size{ 2, 2 }, 42) } -> std::same_as<Grid<int>>;
	{ Grid(2, 2, a)            } -> std::same_as<Grid<int>>;
	{ Grid(2, 2, std::move(a)) } -> std::same_as<Grid<int>>;
	{ Grid(Size{ 2, 2 }, a)            } -> std::same_as<Grid<int>>;
	{ Grid(Size{ 2, 2 }, std::move(a)) } -> std::same_as<Grid<int>>;
	{ Grid({ { 42, 42 }, { 42, 42 } }) } -> std::same_as<Grid<int>>;
	{ Grid(2, 2, Arg::generator = [] { return 42; })         } -> std::same_as<Grid<int>>;
	{ Grid(Size{ 2, 2 }, Arg::generator = [] { return 42; }) } -> std::same_as<Grid<int>>;
	{ Grid(2, 2, Arg::indexedGenerator = [](Point) { return 42; })         } -> std::same_as<Grid<int>>;
	{ Grid(Size{ 2, 2 }, Arg::indexedGenerator = [](Point) { return 42; }) } -> std::same_as<Grid<int>>;
});

void Main()
{
	while (System::Update())
	{

	}
}

@Reputeless Reputeless moved this to Investigating in v0.6 Roadmap Jun 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Investigating
Development

Successfully merging this pull request may close these issues.

1 participant