109 std::string result =
"FOREIGN KEY (";
112 std::string local_names;
113 get_column_names<0,
sizeof...(ColumnPtrs) / 2>(local_names);
114 result += local_names;
117 result +=
") REFERENCES ";
118 std::string ref_table_name = get_referenced_table_name();
119 result += ref_table_name +
"(";
121 std::string ref_names;
122 get_column_names<
sizeof...(ColumnPtrs) / 2,
sizeof...(ColumnPtrs)>(ref_names);
144 template <
size_t Start,
size_t End>
145 void get_column_names(std::string& names)
const {
146 get_column_names_impl<Start, End, ColumnPtrs...>(names);
150 template <
size_t Start,
size_t End,
auto FirstColumnPtr,
auto... RestColumnPtrs>
151 void get_column_names_impl(std::string& names)
const {
152 if constexpr (Start == 0) {
154 using column_type =
typename member_pointer_type<
decltype(FirstColumnPtr)>::type;
155 names = std::string(column_type::name);
158 if constexpr (
sizeof...(RestColumnPtrs) > 0 && 1 < End) {
159 get_column_names_impl<0, End - 1, RestColumnPtrs...>(names,
true);
163 get_column_names_impl<Start - 1, End - 1, RestColumnPtrs...>(names);
168 template <
size_t Start,
size_t End,
auto FirstColumnPtr,
auto... RestColumnPtrs>
169 void get_column_names_impl(std::string& names,
bool append)
const {
171 using column_type =
typename member_pointer_type<
decltype(FirstColumnPtr)>::type;
172 names +=
", " + std::string(column_type::name);
176 if constexpr (
sizeof...(RestColumnPtrs) > 0 && 1 < End) {
177 get_column_names_impl<0, End - 1, RestColumnPtrs...>(names, append);
182 template <
size_t Start,
size_t End>
183 void get_column_names_impl(std::string& names)
const {
187 template <
size_t Start,
size_t End>
188 void get_column_names_impl(std::string& names,
bool append)
const {
193 std::string get_referenced_table_name()
const {
195 return get_ref_table_name_impl<
sizeof...(ColumnPtrs) / 2, ColumnPtrs...>();
199 template <
size_t Index,
auto FirstColumnPtr,
auto... RestColumnPtrs>
200 std::string get_ref_table_name_impl()
const {
201 if constexpr (Index == 0) {
203 using table_type =
typename member_pointer_class<
decltype(FirstColumnPtr)>::type;
204 return std::string(table_type::table_name);
207 return get_ref_table_name_impl<Index - 1, RestColumnPtrs...>();
212 template <
size_t Index>
213 std::string get_ref_table_name_impl()
const {
215 static_assert(Index == 0,
216 "Invalid foreign key template parameters: could not determine referenced table");
221 template <
typename T>
222 struct member_pointer_class;
224 template <
typename C,
typename T>
225 struct member_pointer_class<T C::*> {
230 template <
typename T>
231 struct member_pointer_type;
233 template <
typename C,
typename T>
234 struct member_pointer_type<T C::*> {
246 std::tuple<std::integral_constant<decltype(LocalColumns), LocalColumns>...>,
247 std::tuple<std::integral_constant<decltype(ReferencedColumns), ReferencedColumns>...>> {
248 using type = std::conditional_t<
sizeof...(LocalColumns) == 1,
249 foreign_key<(LocalColumns, ...), (ReferencedColumns, ...)>,